json - downgoon/hello-world GitHub Wiki
问题列表
问题-1: 序列化与反序列化
假设有个City
对象,需要序列化和反序列化:
public class City {
private String name;
private Integer gdp;
}
序列化相对简单,把对象弄成{'name': 'wangyi', 'gdp': 1867 }
就好了。
但是反序列化,它怎么知道序列化成哪个类呢?
答案:反序列化时,需要在输入参数指定Class类型,比如Jackson2的做法是objectMapper.readValue(byte[] , City.class)
。
问题-2: JSON 编辑
构造一个JSON对象或数组,并对它进行:增、删、改和查。大多数情况,我们是“查”,编辑(增、删和改)涉及比较少。
假设父JSON是:P, 子JSON是S0和S1,其中S0是P已有的,S1是新加入的P的。伪代码表示:
S0 = P.get(0);
P.add(S1);
测试点:
- 修改S0的属性取值,观察P对象是否发生变化?
- 修改S1的属性取值,观察P对象是否发生变化?
实验-2:JSON编辑
进入测试代码
$ git checkout json
$ git checkout json-c1-updateproblem
json-lib 测试
代码UpdateProblemJsonlib.java
:
public static void jsonUpdate(String[] args) throws Exception {
String originJsonText = "[{\"name\": \"jinan\", \"gdp\": 123},{\"name\": \"qingdao\", \"gdp\": 456}]";
JSONArray citiesJsonArray = JSONArray.fromObject(originJsonText);
// get 浅拷贝(共享)
JSONObject jinanJson = citiesJsonArray.getJSONObject(0);
System.out.println("jinan origin << " + jinanJson);
System.out.println("cities origin << " + citiesJsonArray);
System.out.println();
jinanJson.element("gdp", "321");
System.out.println("jinan changed >> " + jinanJson);
System.out.println("cities changed ? >> " + citiesJsonArray); // true
// add 深拷贝(复制)
System.out.println();
JSONObject hezeJson = JSONObject.fromObject("{\"name\": \"heze\", \"gdp\": 789}");
citiesJsonArray.add(hezeJson);
System.out.println("cities after heze added >> " + citiesJsonArray);
System.out.println();
hezeJson.element("gdp", 987);
System.out.println("heze updated >> " + hezeJson);
System.out.println("cities after heze updated ? >> " + citiesJsonArray); // false
// [{"name":"jinan","gdp":"321"},{"name":"qingdao","gdp":456},{"name":"heze","gdp":789}]
// heze 数据依然是 789,并没有发生变化。这种特性跟JAVA对象是不一样的。
}
上述代码对一个JSONArray,取出第一个对象,假设S0;加入了新对象,假设S1。并分别对S0和S1的属性取值做更新,观察JSONArray是否也发生变化,以便判断“浅拷贝(共享模式)”还是“深拷贝(复制模式)”。
jinan origin << {"name":"jinan","gdp":123}
cities origin << [{"name":"jinan","gdp":123},{"name":"qingdao","gdp":456}]
jinan changed >> {"name":"jinan","gdp":"321"}
cities changed ? >> [{"name":"jinan","gdp":"321"},{"name":"qingdao","gdp":456}]
cities after heze added >> [{"name":"jinan","gdp":"321"},{"name":"qingdao","gdp":456},{"name":"heze","gdp":789}]
heze updated >> {"name":"heze","gdp":987}
cities after heze updated ? >> [{"name":"jinan","gdp":"321"},{"name":"qingdao","gdp":456},{"name":"heze","gdp":789}]
heze updated >> {"name":"heze","gdp":987}
新加入的对象S1更新后,对应的JSONArray并不会更新。
jackson2 测试
代码UpdateProblemJackson2.java
:
public static void jsonUpdate() throws Exception {
String originJsonText = "[{\"name\": \"jinan\", \"gdp\": 123},{\"name\": \"qingdao\", \"gdp\": 456}]";
ObjectMapper mapper = new ObjectMapper();
// JSONArray citiesJsonArray = JSONArray.fromObject(originJsonText);
ArrayNode citiesJsonArray = mapper.readValue(originJsonText.getBytes(), ArrayNode.class);
// JSONObject jinanJson = citiesJsonArray.getJSONObject(0); // get 浅拷贝(共享)
ObjectNode jinanJson = (ObjectNode) citiesJsonArray.get(0);
System.out.println("jinan origin << " + jinanJson);
System.out.println("cities origin << " + citiesJsonArray);
System.out.println();
// jinanJson.element("gdp", "321");
jinanJson.put("gdp", 321);
System.out.println("jinan changed >> " + jinanJson);
System.out.println("cities changed ? >> " + citiesJsonArray); // true
System.out.println();
// JSONObject hezeJson = JSONObject.fromObject("{\"name\": \"heze\", \"gdp\": 789}");
ObjectNode hezeJson = mapper.readValue("{\"name\": \"heze\", \"gdp\": 789}", ObjectNode.class);
citiesJsonArray.add(hezeJson); // add 深拷贝(复制)
System.out.println("cities after heze added >> " + citiesJsonArray);
System.out.println();
// hezeJson.element("gdp", 987);
hezeJson.put("gdp", 987);
System.out.println("heze updated >> " + hezeJson);
System.out.println("cities after heze updated ? >> " + citiesJsonArray); // false
// [{"name":"jinan","gdp":"321"},{"name":"qingdao","gdp":456},{"name":"heze","gdp":789}]
// heze 数据依然是 789,并没有发生变化。这种特性跟JAVA对象是不一样的。
}
运行结果:
jinan origin << {"name":"jinan","gdp":123}
cities origin << [{"name":"jinan","gdp":123},{"name":"qingdao","gdp":456}]
jinan changed >> {"name":"jinan","gdp":321}
cities changed ? >> [{"name":"jinan","gdp":321},{"name":"qingdao","gdp":456}]
cities after heze added >> [{"name":"jinan","gdp":321},{"name":"qingdao","gdp":456},{"name":"heze","gdp":789}]
heze updated >> {"name":"heze","gdp":987}
cities after heze updated ? >> [{"name":"jinan","gdp":321},{"name":"qingdao","gdp":456},{"name":"heze","gdp":987}]
发现当"heze"城市的gdb更新后,无论是heze对象,还是JSONArray,都更新了。这个行为跟json-lib不一样,但jackson2更符合大家预期。
fastjson 测试
进入代码:
$ git checkout json
$ git checkout json-c2-fastjson
查看代码:UpdateProblemFastjson.java
public static void main(String[] args) throws Exception {
String originJsonText = "[{\"name\": \"jinan\", \"gdp\": 123},{\"name\": \"qingdao\", \"gdp\": 456}]";
JSONArray citiesJsonArray = JSON.parseArray(originJsonText);
JSONObject jinanJson = citiesJsonArray.getJSONObject(0); // get 浅拷贝(共享)
System.out.println("jinan origin << " + jinanJson);
System.out.println("cities origin << " + citiesJsonArray);
System.out.println();
jinanJson.put("gdp", 321);
System.out.println("jinan changed >> " + jinanJson);
System.out.println("cities changed ? >> " + citiesJsonArray); // true
System.out.println();
JSONObject hezeJson = JSON.parseObject("{\"name\": \"heze\", \"gdp\": 789}");
citiesJsonArray.add(hezeJson); // add 深拷贝(复制)
System.out.println("cities after heze added >> " + citiesJsonArray);
System.out.println();
hezeJson.put("gdp", 987);
System.out.println("heze updated >> " + hezeJson);
System.out.println("cities after heze updated ? >> " + citiesJsonArray); // false
}
运行结果:
heze updated >> {"gdp":987,"name":"heze"}
cities after heze updated ? >> [{"gdp":321,"name":"jinan"},{"gdp":456,"name":"qingdao"},{"gdp":987,"name":"heze"}]
fastjson 真心很赞:
- 命名上,跟json-lib很易懂。
- 行为上,跟jackson一致。
此外,fastjson还解决了非常多的问题,都在FAQ列出来了。其中还包括兼容IE6下JSON不支持中文(JSON中含中文的需要转化成Unicode编码)。
关于 fastjson 的性能:
fastjson的性能如何?
fastjson是目前java语言中最快的json库,比自称最快的jackson速度要快,第三方独立测试结果看这里:https://github.com/eishay/jvm-serializers/wiki/Staging-Results 。
自行做性能测试时,关闭循环引用检测的功能。
JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect) VO vo = JSON.parseObject("...", VO.class, Feature.DisableCircularReferenceDetect)
>这里有jackson作者cowtowncoder等人对fastjson的性能评价: https://groups.google.com/forum/#!topic/java-serialization-benchmarking/8eS1KOquAhw
# 结论
- 两个关注的json: 关注阿里的 fastjson 和 spring默认的jackson (功能丰富) 即可。
- 两个落后的json: gson 和 json-lib 都很落后了。