Json已成为计算机编程中最常用的数据传输和存储格式之一,所以对Json的序列化和反序列化工具的选择也是互联网系统中比较重要的环节,尤其在高并发下的执行效率,可能会直接影响系统的吞吐率。本文将从功能和性能两方面对常用的四种Json处理工具进行对比,以便选出符合我们系统需要的Json处理工具。
项目 |
json-lib |
fastJson |
Jackson |
Gson |
最新版本号 |
2.4 |
1.2.51 |
2.97 |
2.8.5 |
最后更新 |
2010/12/14 |
2018/9/30 |
2018/9/19 |
2018/5/22 |
被引用次数 |
426 |
1492 |
5185 |
8655 |
是否支持注解 |
No |
Yes |
Yes |
Yes |
Map 中的key为Long时 |
报错 |
正常输出,不是标准格式 |
会把key转成String |
会把key转成String |
特殊字符 |
支持 |
支持 |
支持 |
支持 |
控制字符 |
支持 |
支持 |
支持 |
支持 |
表情字符 |
支持 |
支持 |
支持 |
支持 |
从上表可以得出以下结论:
其它说明:
1、 Jackson、json-lib反序列化时,要求所有涉及的Bean必须存在默认的构造函数
2、 fastJson、json-lib反序列化,再序列化之后得到的JSON与之前可能不一致,因为Map的顺序会变,而Jackson、gson反序列化之后是一致的,其使用了LinkedHashMap保证顺序
3、 fastJson、Gson输出json时会忽略值为null的字段;对于值为null的字段,jackson输出null,而json-lib输出空字符串
4、 fastJson反序列化时,二级对象中的List出现过没有被反序列化的情况,但后来测试又可以反序列化了,目前还没有找到规律
测试环境:本地Windows、2核8G内存,64位OS
Bean对象:小对象,输出Json后约1.83KB
结论:
测试环境:本地Windows、2核8G内存,64位OS
Bean对象:大对象,输出Json后约8.99KB
结论:
测试环境:本地Windows、2核8G内存,64位OS
Bean对象:特大对象,输出Json后约56.1KB。因在小对象测试中证明json-lib和gson在高并发下效率不好,所以大对象测试中忽略这两个包,只对比fastjson和jackson。
结论:
测试环境:本地Windows、2核8G内存,64位OS
输入数据:小对象,输入Json约1.83KB
总结:
测试环境:本地Windows、2核8G内存,64位OS
输入数据:大对象,输入Json约9.83KB
结论:
测试环境:本地Windows、2核8G内存,64位OS
输入数据:特大对象,输入Json约56.1KB
结论:
经过以上测试及对比,基本可以得出结论:Jackson工具包(测试中使用2.9.5版本)在功能和性能方面都表现的更出色,在新开发系统时可以考虑使用Jackson进行JSON数据的处理。理由如下:
在使用Jackson时,有一些注意事项,需要在编写代码时注意,具体如下:
1) 反序列化时,要求 所有涉及的Bean必须存在默认的构造函数 ,否则会报错;
2) 反序列化时,如果json中有部分字段是对象中不存在的属性,或对象中无get/set方法,会报“UnrecognizedPropertyException”,解决方法是:
在类中添加 @JsonIgnoreProperties(ignoreUnknown = true),
或者代码中设置:
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
3) 反序列化的类是抽象类或者接口,就会导致“Can not construct instance of”这个异常。
解决方法:添加@JsonDeserialize(as = Cat.class)注解
如下:
Json文件:
{"id":1001,"name":"布莱德","weight":1.67,"animal":{"color":"Blue"}}
4) 当反序列化的JSON中包含了单引号而不是双引号的时候,会抛“ Unexpected character (''' (code 39)) ”异常,
如Json:{"id":1001,"name":'布莱德','weight':1.67, "feild1": 56}
解决方法:
JsonFactory factory = new JsonFactory();
factory.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
ObjectMapper mapper = new ObjectMapper(factory);
1) 修改POM文件
旧依赖 |
新依赖 |
<dependency> <groupId>org.codehaus.jackson</groupId> <artifactId> jackson - mapper - asl </artifactId> <version>1.x.x</version> </dependency> |
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId> jackson -core</artifactId> <version>2.9.5</version> </dependency> |
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId> jackson - databind </artifactId> <version>1.x.x</version> </dependency> |
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId> jackson - databind </artifactId> <version> 2.9.5 </version> </dependency> |
2) 包名更改
所有以org.codehaus.jackson开头的包名都替换成com.fasterxml.jackson开头的。
3) 设置属性的代码调整
SerializationConfig.Feature.* 改成 SerializationFeature.*
DeserializationConfig.Feature.* 改成 DeserializationFeature.*