json和xml与java类互相转化
json转为xml,我下面的代码用的是pom.xml依赖是这样:
文/程忠 浏览次数:0次 2020-07-26 09:54:46
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.5</version> </dependency> <dependency> <groupId>org.dom4j</groupId> <artifactId>dom4j</artifactId> <version>2.1.3</version> </dependency>
生成的xml认为只有一个根结点,并定义域名空间(xmlns)这个类用的命名空间是ebay的。
调用入口是:Json2XmlUtil.jsonToXml
工具类如下:
package com.xx.saas.ebay.util; import java.io.ByteArrayOutputStream; import java.util.Map.Entry; import java.util.Set; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; public class Json2XmlUtil{ public static String jsonToXml(JsonObject jsonObject,Class cls) { Document document = DocumentHelper.createDocument(); String rootNodeName=cls.getSimpleName(); Element parentElement=document.addElement(rootNodeName,"urn:ebay:apis:eBLBaseComponents"); Element ee = toXml(jsonObject, document,parentElement, null); return document.asXML(); } private static String upperFirstChar(String name){ return String.valueOf(name.charAt(0)).toUpperCase()+name.substring(1); } /** * 将json字符串转换成xml * * @param jsonElement * 待解析json对象元素 * @param parentElement * 上一层xml的dom对象 * @param name * 父节点 */ public static Element toXml(JsonElement jsonElement,Document document, Element parentElement, String name) { if (jsonElement instanceof JsonArray) { //是json数据,需继续解析 JsonArray sonJsonArray = (JsonArray)jsonElement; for (int i = 0; i < sonJsonArray.size(); i++) { Element curentElement=parentElement.addElement(upperFirstChar(name)); JsonElement curJson = sonJsonArray.get(i); toXml(curJson,document, curentElement, null); } }else if (jsonElement instanceof JsonObject) { //说明是一个json对象字符串,需要继续解析 JsonObject sonJsonObject = (JsonObject) jsonElement; Element currentElement = null; if (name != null) { currentElement = parentElement.addElement(upperFirstChar(name)); } Set<Entry<String, JsonElement>> set = sonJsonObject.entrySet(); for (Entry<String, JsonElement> s : set) { toXml(s.getValue(),document, currentElement != null ? currentElement : parentElement, s.getKey()); } } else { //说明是一个键值对的key,可以作为节点插入了 addAttribute(parentElement, name, jsonElement.getAsString()); } return parentElement; } /** * * @param element 父节点 * @param name 子节点的名字 * @param value 子节点的值 */ public static void addAttribute(Element element, String name, String value) { if(name==null){ //"Value":["Yellow","Red"] 这种情况,name为空,且已生成了上层节点(Value) //最终生成<Value>Yellow</Value><Value>Red</Value> element.addText(value); return; } if(name.startsWith("attr_")) { element.addAttribute(upperFirstChar(name.replace("attr_", "")), value); } else if(name.startsWith("value_")) { element.addText(value); }else { //增加子节点,并为子节点赋值 Element el = element.addElement(upperFirstChar(name)); el.addText(value); } } }
xml转为json:
对于即有属性又有内容的节点有特殊处理,该节点转为一个json的节点,下面有attr_与value_两个值。
这里还有一个问题是,对节点名里的attributer的解析,如果xml里没有,那么要添加进去才能执行上面的规则。
xml一个结点下的相同的一组结点,按理应解析为数组类型,但在json里并没体现。在json转java类时,指定的结点可定义为List
package net.highersoft.util; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.StringReader; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; import com.google.gson.JsonObject; public class XML2JsonDom4j2 { /** * XML字符串转JSON对象 * * @param xml * xml字符串 * @return JSON对象 * @throws DocumentException */ public static JsonObject xmlToJson(String xml) throws DocumentException { JsonObject json = new JsonObject(); SAXReader reader = new SAXReader(); Document document = reader.read(new StringReader(xml)); Element root = document.getRootElement(); json.add(root.getName(), elementToJson(root)); return json; } /** * Element对象转JSON对象 * * @param element * Element对象 * @return JSON对象 */ public static JsonObject elementToJson(Element element) { JsonObject json = new JsonObject(); // 如果有属性先放属性 for (Attribute attr : element.attributes()) { json.addProperty("attr_" + attr.getName(), attr.getValue()); } // 再放子元素 for (Object child : element.elements()) { Element ec = (Element) child; JsonObject children = new JsonObject(); // 如果有属性先放属性 for (Attribute attr : ec.attributes()) { children.addProperty("attr_" + attr.getName(), attr.getValue()); } if (children.size() > 0) { json.add(ec.getName(), children); } if (ec.elements().isEmpty()) { //如果没有子元素,没有属性(children.length()==0)则直接放为值。如果已有属性,则值的key为value_ if (children.size() == 0) { json.addProperty(ec.getName(), ec.getText().trim()); } else { children.addProperty("value_", ec.getText()); json.add(ec.getName(), children); } } else { //有子元素 JsonObject jsonTmp = elementToJson(ec); for (String key : jsonTmp.keySet()) { children.add(key, jsonTmp.get(key)); } json.add(ec.getName(), children); } } return json; } public static void main(String args[]) throws Exception{ String path="tmp2.xml"; //对于ebay的xml文档的特殊处理 //example:https://developer.ebay.com/DevZone/xML/docs/Reference/eBay/GetSellerTransactions.html StringBuffer sb=new StringBuffer(); BufferedReader br=new BufferedReader(new InputStreamReader(Xml2Json.class.getClassLoader().getResourceAsStream(path),"UTF-8")); String str=null; while((str=br.readLine())!=null) { String line=str.trim(); if(line.startsWith("<!--")) { continue; }else { if(!line.endsWith(">")) { line=line.substring(0,line.lastIndexOf(">")+1); } sb.append(line+"\r\n"); } } br.close(); String xml=sb.toString(); System.out.println(xml); //不处理的xml可直接调用下行 JsonObject json=xmlToJson(xml); System.out.println(json); } }
ebay的xml文档格式如下:
<?xml version="1.0" encoding="utf-8"?> <GetSellerTransactionsRequest xmlns="urn:ebay:apis:eBLBaseComponents"> <!-- Call-specific Input Fields --> <IncludeCodiceFiscale> boolean </IncludeCodiceFiscale> <IncludeContainingOrder> boolean </IncludeContainingOrder> <IncludeFinalValueFee> boolean </IncludeFinalValueFee> <InventoryTrackingMethod> InventoryTrackingMethodCodeType </InventoryTrackingMethod> <ModTimeFrom> dateTime </ModTimeFrom> <ModTimeTo> dateTime </ModTimeTo> <NumberOfDays> int </NumberOfDays> <Pagination> PaginationType <EntriesPerPage> int </EntriesPerPage> <PageNumber> int </PageNumber> </Pagination> <SKUArray> SKUArrayType <SKU> SKUType (string) </SKU> <!-- ... more SKU values allowed here ... --> </SKUArray> <!-- Standard Input Fields --> <DetailLevel> DetailLevelCodeType </DetailLevel> <!-- ... more DetailLevel values allowed here ... --> <ErrorLanguage> string </ErrorLanguage> <MessageID> string </MessageID> <OutputSelector> string </OutputSelector> <!-- ... more OutputSelector values allowed here ... --> <Version> string </Version> <WarningLevel> WarningLevelCodeType </WarningLevel> </GetSellerTransactionsRequest>
json转为Java类:
这个版本可识别int,boolean类型。
另外还可指定那些结点需要转为数组(List)类型的。这地方有点缺陷,不支持同一个xml,相同节点名,有的是集合,有的是非集合,这样在这里有就逻辑冲突。
package net.highersoft.util; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import lombok.Data; public class JSON2Class { //ebay xml文档转换为Java基本类型 static Map<String,String> convertMap=new HashMap<String,String>(){ { put("string","String"); put("boolean","Boolean"); put("int","Integer"); //put("dateTime","Date"); } }; //要把类型生成为List的节点名 static List<String> listItem=new ArrayList() {{ //刊登作品接口 add("CrossBorderTrade"); add("Value"); add("NameValueList"); add("Compatibility"); add("ListingEnhancement"); add("PaymentMethods"); add("PictureURL"); add("ExcludeShipToLocation"); add("ShipToLocation"); add("InternationalShippingServiceOption"); add("ShippingServiceOptions"); add("ShippingServiceCostOverride"); add("ShipToLocations"); add("PictureURL"); add("VariationSpecificPictureSet"); add("VariationSpecifics"); add("Variation"); /* add("SKU"); add("DetailLevel"); add("OutputSelector"); */ }}; public static void main(String a[]) throws Exception{ String path="demo_item.json"; StringBuffer sb=new StringBuffer(); BufferedReader br=new BufferedReader(new InputStreamReader(JSON2Class.class.getClassLoader().getResourceAsStream(path),"UTF-8")); String str=null; while((str=br.readLine())!=null) { sb.append(str); } br.close(); String xml=sb.toString(); JsonObject jsonObject = new JsonParser().parse(xml).getAsJsonObject(); //json转为BeanEntity对象 BeanEntity be=new BeanEntity(); Entry<String,JsonElement> root=jsonObject.entrySet().iterator().next(); be.setName(root.getKey()); List<BeanPropertyEntity> props=new ArrayList<>(); be.setProperties(props); List<BeanEntity> childrenCls=new ArrayList<>(); iterator(childrenCls,props,root.getValue().getAsJsonObject()); String packVal="package com.xx.saas.ebay.controller.dto.item.addfixedpriceitem;"; String targetPath="/Users/chengzhong/work/xx_work/idea_workspace/ebay-oauth-java-client/src/test/resources/tmp"; for(File f:new File(targetPath).listFiles()) { f.delete(); } Thread.sleep(1000); str=convertBean(packVal,be); System.out.println(str); printFile(targetPath,be,str); for(BeanEntity tmp: childrenCls) { str=convertBean(packVal,tmp); System.out.println(str); printFile(targetPath,tmp,str); } } private static void printFile(String targetPath,BeanEntity be,String txt) throws Exception{ String file=targetPath+File.separator+be.getName()+".java"; PrintWriter pw=new PrintWriter(new OutputStreamWriter(new FileOutputStream(file),"UTF-8")); pw.print(txt); pw.close(); } private static void iterator(List<BeanEntity> childrenCls,List<BeanPropertyEntity> props,JsonObject jsonObject) { for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) { JsonElement value = entry.getValue(); if (value.isJsonArray()) { JsonArray jsonArray = value.getAsJsonArray(); // 数组长度为0时将其处理,防止Gson转换异常 if (jsonArray.size() == 0) { entry.setValue(null); } else { for (JsonElement o : jsonArray) { JsonObject asJsonObject = o.getAsJsonObject(); //iterator(be,asJsonObject); } } }else if (value.isJsonObject()) { JsonObject asJsonObject = value.getAsJsonObject(); BeanPropertyEntity b1=new BeanPropertyEntity(); b1.setName(entry.getKey()); b1.setTypeName(entry.getKey()); props.add(b1); BeanEntity be=new BeanEntity(); be.setName(entry.getKey()); List<BeanPropertyEntity> cprops=new ArrayList<>(); be.setProperties(cprops); childrenCls.add(be); iterator(childrenCls,cprops,asJsonObject); }else if(value.isJsonPrimitive()) { String strVal = value.getAsString(); BeanPropertyEntity b1=new BeanPropertyEntity(); b1.setName(entry.getKey()); String typeName=convertMap.get(strVal); if(typeName!=null) { b1.setTypeName(typeName); }else { b1.setTypeName("String"); } props.add(b1); } } } /** * 类对象转为文本 * @param beanEntity * @return */ private static String convertBean(String packVal,BeanEntity beanEntity) { StringBuffer sb=new StringBuffer(); if(packVal!=null) { sb.append(packVal+"\r\n"); } sb.append("import lombok.Data;"+"\r\n"); sb.append("import java.util.Date;"+"\r\n"); sb.append("import java.util.List;"+"\r\n"); sb.append("@Data"+"\r\n"); sb.append("public class "+beanEntity.getName()+"{"+"\r\n"); for(BeanPropertyEntity prop:beanEntity.properties) { //类属性,首字母小写 String valName=prop.getName(); valName=valName.substring(0,1).toLowerCase()+valName.substring(1); //如果是List类型的,转为List String typeName=prop.getTypeName(); if(listItem.contains(typeName)) { //类类型 typeName="List<"+typeName+">"; }else if(convertMap.containsValue(typeName)&&listItem.contains(prop.getName())) { //基本类型,值是多值的 typeName="List<"+typeName+">"; } sb.append("\tprivate "+typeName+" "+valName+";"+"\r\n"); } sb.append("}"); return sb.toString(); } @Data public static class BeanEntity{ //实体类 private String name; private List<BeanPropertyEntity> properties; } @Data public static class BeanPropertyEntity{ //字段名 private String name; //类型名 private String typeName; } }
相关阅读
评论:
↓ 广告开始-头部带绿为生活 ↓
↑ 广告结束-尾部支持多点击 ↑