【Java123】XML与JSON互相转化
http://www.bejson.com/json2javapojo/new/
https://www.cnblogs.com/111testing/p/9162229.html
https://wenku.baidu.com/view/8364d04b86c24028915f804d2b160b4e777f8102.html
https://www.jianshu.com/p/8dadd9a232b1
使用org.json的Demo:
1 import org.apache.commons.io.IOUtils; 2 import org.json.JSONException; 3 import org.json.JSONObject; 4 import org.json.XML; 5 6 import java.io.IOException; 7 import java.io.InputStream; 8 9 public class XML2JSON { 10 11 public XML2JSON(){} 12 13 public static String xml2jsonString(String filepath) throws IOException, JSONException { 14 15 InputStream in = XML2JSON.class.getResourceAsStream(filepath); 16 String xml = IOUtils.toString(in); 17 System.out.print(xml); 18 System.out.println(); 19 20 JSONObject xmlJSONObj = XML.toJSONObject(xml); 21 String jsonStr = xmlJSONObj.toString(); 22 System.out.print(jsonStr); 23 24 return xmlJSONObj.toString(); 25 26 } 27 28 29 public static void main(String[] args) throws JSONException, IOException { 30 31 String string = xml2jsonString("simple.xml"); 32 System.out.println(string); 33 34 } 35 36 }
测试1:
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<credit>NOAA's National Weather Service</credit>
<credit_URL>http://weather.gov/</credit_URL>
</book>
<url>http://weather.gov/images/xml_logo.gif</url>
<title>NOAA's National Weather Service</title>
<link>http://weather.gov</link>
</image>
<station_id>KJFK</station_id>
<latitude>40.66</latitude>
<longitude>-73.78</longitude>
<observation_time_rfc822>
Mon, 11 Feb 2008 06:51:00 -0500 EST
</observation_time_rfc822>
<temp_f>11</temp_f>
<temp_c>-12</temp_c>
<relative_humidity>36</relative_humidity>
<wind_dir>West</wind_dir>
<wind_degrees>280</wind_degrees>
<wind_mph>18.4</wind_mph>
<wind_gust_mph>29</wind_gust_mph>
<pressure_mb>1023.6</pressure_mb>
<pressure_in>30.23</pressure_in>
<dewpoint_f>-11</dewpoint_f>
<dewpoint_c>-24</dewpoint_c>
<windchill_f>-7</windchill_f>
<windchill_c>-22</windchill_c>
<visibility_mi>10.00</visibility_mi>
http://weather.gov/weather/images/fcicons/
</icon_url_base>
<icon_url_name>nfew.jpg</icon_url_name>
<two_day_history_url>
http://www.weather.gov/data/obhistory/KJFK.html
</two_day_history_url>
<disclaimer_url>
http://weather.gov/disclaimer.html
</disclaimer_url>
<copyright_url>
http://weather.gov/disclaimer.html
</copyright_url>
测试2:
<!-- Edited with XML Spy v2007 (http://www.altova.com) -->
<current_observation>
<author>Helen</author>
<author>Jason</author>
</book>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<credit>NOAA's National Weather Service</credit>
<credit_URL>http://weather.gov/</credit_URL>
</book>
{"current_observation":{"book":["","",{"id":"bk98"},{"id":"bk99","content":"Hello World!"},{"author":["Helen","Jason"],"id":"bk100"},{"author":"Gambardella, Matthew","price":44.95,"genre":"Computer","description":"An in-depth look at creating applications\r\n\t\t\twith XML.","id":"bk101","title":"XML Developer's Guide","publish_date":"2000-10-01"},{"author":"Ralls, Kim","credit_URL":"http://weather.gov/","id":"bk102","title":"Midnight Rain","credit":"NOAA's National Weather Service"}]}}
对比在线转换
http://www.bejson.com/xml2json/
JSON转换结果对比上边有几点不同:
1. 忽略无意义的book数据
2. 缺省key值为#text
{ "current_observation": { "book": [ { "-id": "bk98" }, { "-id": "bk99", "#text": "Hello World!" }, { "-id": "bk100", "author": [ "Helen", "Jason" ] }, { "-id": "bk101", "author": "Gambardella, Matthew", "title": "XML Developer's Guide", "genre": "Computer", "price": "44.95", "publish_date": "2000-10-01", "description": "An in-depth look at creating applications with XML." }, { "-id": "bk102", "author": "Ralls, Kim", "title": "Midnight Rain", "credit": "NOAA's National Weather Service", "credit_URL": "http://weather.gov/" } ] } }
各路方法,有使用第三方API,或者自写遍历迭代方法。
在针对上述Demo的测试结果做分析,还需要进一步考虑以下几点:
1. 源XML文件自身特殊及复杂情况的转换定义。比如,字段含特殊字符,一个标签含多个属性,多个标签同名,invalid file等。
2. 目标JSON文件的转换定义。比如,各元素是否保持原有顺序,多个同名标签作为数组还是同级对象,等。
3. 转换过程中的异常处理。比如,转换中遇到无法解析而跳出导致该目标文件无效,异常捕获记录,等。
https://blog.csdn.net/bestxiaok/article/details/80443640
还有一个如何测试转换生成的JSON文件是否“正确”?
1. 是否是一个合格的JSON文件?
Why Validate Data as a Separate Step?
- to fail fast
- to avoid data corruption
- to simplify processing code
- to use validation code in tests
比较完备但复杂的做法:使用预定义的JSON-Schema来校验文件
- https://github.com/java-json-tools/json-schema-validator
比较简单直接的做法:使用库加载JSON文件时抛出的异常来判断
2. 如何将测试预期结果JSON文件和待测JSON文件进行比对?(Github上只关注了Java)
- https://github.com/fslev/json-compare
- https://github.com/a2design-inc/json-compare
项目实践中,采用JAXB的Marshaller实现xml到java object的反序列化,再序列化为json时候默认空value=null, 空数组=[],空对象为{}
测试时候,无法直接使用xml->json的处理,因为空属性的加入,无法无中生有,所以只好也走一套反序列化到序列化的流程。代价就是不得不使用项目的java object或者构建一套测试自己的Dao层.....如果时复杂java object的话,本身变动频繁,后期维护代价很大。另一套方案是测试比较结果的处理,无中生有的空字段比较设立ignore list,如有对象变动,仅需更新ignore list即可,但若实现caseBycase Ignore的处理,case处理情况爆炸,代价又太大。
真的是测试要考虑的比代码本身还复杂。。。若测试引入的代码过多,是否有悖初衷呢?
实际项目用三种途径实现XML到JSON的转换。
一、XML->JSON
1 JSONObject xmlJSONObj = XML.toJSONObject(xml); 2 String jsonStr = xmlJSONObj.toString();
二、XML->JavaBean
JAXB
Create - UserJavaBeanClass
1 public static Object xmlToBean(String xmlPath,Class<?> load) throws JAXBException, IOException { 2 3 LocalFileResourceParser fileLoader = new LocalFileResourceParser(); 4 InputStream in = fileLoader.parseFile(xmlPath); 5 6 JAXBContext context = JAXBContext.newInstance(load); 7 Unmarshaller unmarshaller = context.createUnmarshaller(); 8 Object object = unmarshaller.unmarshal(in); 9 return object; 10 }
三、JavaBean->JSON
(1) Gson
// https://mvnrepository.com/artifact/org.json/json
compile group: 'org.json', name: 'json', version: '20160810'
1 Gson gson = new GsonBuilder().serializeNulls().create(); 2 String jsonStr = gson.toJson(metadata);
(2) fastjson
// https://mvnrepository.com/artifact/com.alibaba/fastjson
compile group: 'com.alibaba', name: 'fastjson', version: '1.2.54'
1 public class BeanToJson { 2 3 private static final SerializerFeature[] features = { 4 SerializerFeature.PrettyFormat, // JSON标准格式化输出 5 SerializerFeature.NotWriteRootClassName, // 6 SerializerFeature.WriteClassName, // 7 SerializerFeature.SortField, // 8 SerializerFeature.WriteMapNullValue, // 输出空置字段 9 SerializerFeature.WriteNullListAsEmpty, // list字段如果为null,输出为[],而不是null 10 // SerializerFeature.WriteNullNumberAsZero, // 数值字段如果为null,输出为0,而不是null 11 // SerializerFeature.WriteNullBooleanAsFalse, // Boolean字段如果为null,输出为false,而不是null 12 // SerializerFeature.WriteNullStringAsEmpty, // 字符类型字段如果为null,输出为"",而不是null 13 SerializerFeature.WriteDateUseDateFormat // 日期格式化yyyy-MM-dd HH:mm:ss 14 }; 15 16 public static String toJsonString (Object object) throws JSONException { 17 String jsonStr = JSON.toJSONString(object, true); 18 return jsonStr; 19 } 20 21 public static String toJsonStringWithFeature (Object object) throws JSONException { 22 String jsonStr = JSON.toJSONString(object, BeanToJson.features); 23 return jsonStr; 24 } 25 26 }
比较:
gson可以设置某些feature,若要实现更复杂的feature,需要自己实现。
fastjson可以设置更多的features,满足项目需要。