json和xml与java类互相转化

json转为xml,我下面的代码用的是pom.xml依赖是这样:
<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.dhgate.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.dhgate.saas.ebay.controller.dto.item.addfixedpriceitem;";
		String targetPath="/Users/chengzhong/work/dhgate_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;
		
		
		
	}

}

文/程忠 浏览次数:0次   2020-07-26 09:54:46

相关阅读


评论: