package jef.json; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import jef.tools.StringUtils; import jef.tools.XMLUtils; import org.w3c.dom.Attr; import org.w3c.dom.CDATASection; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import com.alibaba.fastjson.serializer.JSONSerializer; import com.alibaba.fastjson.serializer.ObjectSerializer; import com.alibaba.fastjson.serializer.SerializeWriter; public class XmlJsonSerializer implements ObjectSerializer { public static final String ARRAY_NODE_ATTR_NAME = "_type"; public static final String ARRAY_NODE_ATTR_VALUE = "array"; public static final String NAME_COMPLEX_ARRAY_ELEMENT = "e"; public static final String NAME_PRIMITIVE_ARRAY_ELEMENT = "v"; private static String nodeAsText(Node node) { short type = node.getNodeType(); if (type == Node.ATTRIBUTE_NODE || type == Node.TEXT_NODE) { return StringUtils.unescapeHtml(node.getNodeValue().trim()); } else if (type == Node.CDATA_SECTION_NODE) { return ((CDATASection) node).getTextContent(); } else { return null; } } public static void beginObject(SerializeWriter out) { out.append('{'); } public static void endObject(SerializeWriter out) { out.append('}'); } public static void beginArray(SerializeWriter out) { out.append('['); } public static void endArray(SerializeWriter out) { out.append(']'); } public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,int features){ Node src=(Node)object; SerializeWriter writer=serializer.getWriter(); if(src.getNodeType()==Node.ELEMENT_NODE){ Element e=(Element)src; if(ARRAY_NODE_ATTR_VALUE.equals(e.getAttribute(ARRAY_NODE_ATTR_NAME))){ beginArray(writer); Iterator<Element> elements=XMLUtils.childElements(src).iterator(); if(elements.hasNext()){ Element element=elements.next(); writeElement(serializer,writer,element); while(elements.hasNext()){ element=elements.next(); writer.write(','); writeElement(serializer,writer,element); } } endArray(writer); return ; } }else if(src.getNodeType()==Node.DOCUMENT_NODE){ Element root=((Document)src).getDocumentElement(); write(serializer,root,fieldName,fieldType,features); return ; }else{ throw new IllegalArgumentException(); } //DOcument beginObject(writer); boolean first=true; if(src.getAttributes()!=null){ for(Node node:XMLUtils.toArray(src.getAttributes())){ Attr attr=(Attr)node; String key=attr.getName(); String value=attr.getValue(); writeKeyValue(first,serializer,writer,key,value,features); first=false; } } Map<String,List<Node>> childsMap=new HashMap<String,List<Node>>(); for(Node node:XMLUtils.toArray(src.getChildNodes())){ String name=node.getNodeName(); List<Node> nodes=childsMap.get(name); if(nodes==null){ nodes=new ArrayList<Node>(); childsMap.put(name, nodes); } nodes.add(node); } List<Node> textNodes=childsMap.remove("#text"); if(textNodes!=null && textNodes.size()>0){ StringBuilder nodeText=new StringBuilder(); for(int i=0;i<textNodes.size();i++){ String s=nodeAsText(textNodes.get(i)); if(StringUtils.isEmpty(s))continue; if(i>0)nodeText.append('\n'); nodeText.append(s); } if(nodeText.length()>0){ writeKeyValue(first,serializer,writer,"#text", nodeText.toString(),features); first=false; } } for(String key: childsMap.keySet()){ List<Node> nodes=childsMap.get(key); if(nodes.size()==1){ writeKeyValue(first,serializer,writer,key,nodes.get(0),features); }else{ if(!first) writer.write(','); writer.writeFieldName(key); beginArray(writer); Iterator<Node> nodeIter=nodes.iterator(); if(nodeIter.hasNext()){ Node n=nodeIter.next(); write(serializer,n,null,Node.class,features); while(nodeIter.hasNext()){ writer.write(','); n=nodeIter.next(); write(serializer,n,null,Node.class,features); } } endArray(writer); } first=false; } endObject(writer); } private void writeKeyValue(boolean first,JSONSerializer serializer, SerializeWriter writer, String key, Object value,int features) { if(!first){ writer.write(','); } if("null".equals(value)){ writer.writeFieldName(key); writer.writeNull(); }else if (value instanceof Node){ writer.writeFieldName(key); write(serializer,value,null,Node.class,features); }else{ writer.writeFieldName(key); String s=String.valueOf(value); if("true".equals(s)||"false".equals(s)){ writer.write(s); }else if(s.length()<14 && org.apache.commons.lang.StringUtils.isNumeric(s)){ writer.write(s); }else{ writer.writeString(s); } } } private void writeElement(JSONSerializer serializer, SerializeWriter writer, Element element) { if(NAME_PRIMITIVE_ARRAY_ELEMENT.equals(element.getNodeName())){ writer.writeString(element.getTextContent()); }else{ serializer.write(element); } } }