目前对于java开源的json类库有很多种,下面我们取4个常用的json库进行性能测试对比, 同时根据测试结果分析如果根据实际应用场景选择最合适的json库。
这4个json类库分别为:gson,fastjson,jackson,json-lib。
简单介绍选择一个合适的json库要从多个方面进行考虑:
字符串解析成json性能
字符串解析成javabean性能
javabean构造json性能
集合构造json性能
易用性
先简单介绍下四个类库的身份背景。
gson项目地址:https://github.com/google/gson
gson是目前功能最全的json解析神器,gson当初是为因应google公司内部需求而由google自行研发而来,但自从在2008年五月公开发布第一版后已被许多公司或用户应用。
gson的应用主要为tojson与fromjson两个转换函数,无依赖,不需要例外额外的jar,能够直接跑在jdk上。
在使用这种对象转换之前,需先创建好对象的类型以及其成员才能成功的将json字符串成功转换成相对应的对象。类里面只要有get和set方法,gson完全可以实现复杂类型的json到bean或bean到json的转换,是json解析的神器。
fastjson项目地址:https://github.com/alibaba/fastjson
fastjson是一个java语言编写的高性能的json处理器,由阿里巴巴公司开发。无依赖,不需要例外额外的jar,能够直接跑在jdk上。
fastjson在复杂类型的bean转换json上会出现一些问题,可能会出现引用的类型,导致json转换出错,需要制定引用。fastjson采用独创的算法,将parse的速度提升到极致,超过所有json库。
jackson项目地址:https://github.com/fasterxml/jackson
jackson是当前用的比较广泛的,用来序列化和反序列化json的java开源框架。
jackson社区相对比较活跃,更新速度也比较快, 从github中的统计来看,jackson是最流行的json解析器之一,spring mvc的默认json解析器便是jackson。
jackson优点很多:
jackson 所依赖的jar包较少,简单易用。
与其他 java 的 json 的框架 gson 等相比,jackson 解析大的 json 文件速度比较快。
jackson 运行时占用内存比较低,性能比较好
jackson 有灵活的 api,可以很容易进行扩展和定制。
目前最新版本是2.9.4,jackson 的核心模块由三部分组成:
jackson-core 核心包,提供基于”流模式”解析的相关 api,它包括 jsonpaser 和 jsongenerator。jackson 内部实现正是通过高性能的流模式 api 的 jsongenerator 和 jsonparser 来生成和解析 json。
jackson-annotations 注解包,提供标准注解功能;
jackson-databind 数据绑定包,提供基于”对象绑定” 解析的相关 api( objectmapper )和”树模型” 解析的相关 api(jsonnode);基于”对象绑定” 解析的 api 和”树模型”解析的 api 依赖基于”流模式”解析的 api。
json-lib项目地址:http://json-lib.sourceforge.net/index.html
json-lib最开始的也是应用最广泛的json解析工具,json-lib 不好的地方确实是依赖于很多第三方包,对于复杂类型的转换,json-lib对于json转换成bean还有缺陷, 比如一个类里面会出现另一个类的list或者map集合,json-lib从json到bean的转换就会出现问题。json-lib在功能和性能上面都不能满足现在互联网化的需求。
编写性能测试接下来开始编写这四个库的性能测试代码。
添加maven依赖当然首先是添加四个库的maven依赖,公平起见,我全部使用它们最新的版本:
<!-- json libs--><dependency> <groupid>net.sf.json-lib</groupid> <artifactid>json-lib</artifactid> <version>2.4</version> <classifier>jdk15</classifier></dependency><dependency> <groupid>com.google.code.gson</groupid> <artifactid>gson</artifactid> <version>2.8.2</version></dependency><dependency> <groupid>com.alibaba</groupid> <artifactid>fastjson</artifactid> <version>1.2.46</version></dependency><dependency> <groupid>com.fasterxml.jackson.core</groupid> <artifactid>jackson-databind</artifactid> <version>2.9.4</version></dependency><dependency> <groupid>com.fasterxml.jackson.core</groupid> <artifactid>jackson-annotations</artifactid> <version>2.9.4</version></dependency>
四个库的工具类fastjsonutil.java
public class fastjsonutil { public static string bean2json(object obj) { return json.tojsonstring(obj); } public static <t> t json2bean(string jsonstr, class<t> objclass) { return json.parseobject(jsonstr, objclass); }}
gsonutil.java
public class gsonutil { private static gson gson = new gsonbuilder().create(); public static string bean2json(object obj) { return gson.tojson(obj); } public static <t> t json2bean(string jsonstr, class<t> objclass) { return gson.fromjson(jsonstr, objclass); } public static string jsonformatter(string uglyjsonstr) { gson gson = new gsonbuilder().setprettyprinting().create(); jsonparser jp = new jsonparser(); jsonelement je = jp.parse(uglyjsonstr); return gson.tojson(je); }}
jacksonutil.java
public class jacksonutil { private static objectmapper mapper = new objectmapper(); public static string bean2json(object obj) { try { return mapper.writevalueasstring(obj); } catch (jsonprocessingexception e) { e.printstacktrace(); return null; } } public static <t> t json2bean(string jsonstr, class<t> objclass) { try { return mapper.readvalue(jsonstr, objclass); } catch (ioexception e) { e.printstacktrace(); return null; } }}
jsonlibutil.java
public class jsonlibutil { public static string bean2json(object obj) { jsonobject jsonobject = jsonobject.fromobject(obj); return jsonobject.tostring(); } @suppresswarnings("unchecked") public static <t> t json2bean(string jsonstr, class<t> objclass) { return (t) jsonobject.tobean(jsonobject.fromobject(jsonstr), objclass); }}
准备model类这里我写一个简单的person类,同时属性有date、list、map和自定义的类fullname,最大程度模拟真实场景。
public class person { private string name; private fullname fullname; private int age; private date birthday; private list<string> hobbies; private map<string, string> clothes; private list<person> friends; // getter/setter省略 @override public string tostring() { stringbuilder str = new stringbuilder("person [name=" + name + ", fullname=" + fullname + ", age=" + age + ", birthday=" + birthday + ", hobbies=" + hobbies + ", clothes=" + clothes + "]"); if (friends != null) { str.append("friends:"); for (person f : friends) { str.append(" ").append(f); } } return str.tostring(); }}
public class fullname { private string firstname; private string middlename; private string lastname; public fullname() { } public fullname(string firstname, string middlename, string lastname) { this.firstname = firstname; this.middlename = middlename; this.lastname = lastname; } // 省略getter和setter @override public string tostring() { return "[firstname=" + firstname + ", middlename=" + middlename + ", lastname=" + lastname + "]"; }}
json序列化性能基准测试@benchmarkmode(mode.singleshottime)@outputtimeunit(timeunit.seconds)@state(scope.benchmark)public class jsonserializebenchmark { /** * 序列化次数参数 */ @param({"1000", "10000", "100000"}) private int count; private person p; public static void main(string[] args) throws exception { options opt = new optionsbuilder() .include(jsonserializebenchmark.class.getsimplename()) .forks(1) .warmupiterations(0) .build(); collection<runresult> results = new runner(opt).run(); resultexporter.exportresult("json序列化性能", results, "count", "秒"); } @benchmark public void jsonlib() { for (int i = 0; i < count; i++) { jsonlibutil.bean2json(p); } } @benchmark public void gson() { for (int i = 0; i < count; i++) { gsonutil.bean2json(p); } } @benchmark public void fastjson() { for (int i = 0; i < count; i++) { fastjsonutil.bean2json(p); } } @benchmark public void jackson() { for (int i = 0; i < count; i++) { jacksonutil.bean2json(p); } } @setup public void prepare() { list<person> friends=new arraylist<person>(); friends.add(createaperson("小明",null)); friends.add(createaperson("tony",null)); friends.add(createaperson("陈小二",null)); p=createaperson("邵同学",friends); } @teardown public void shutdown() { } private person createaperson(string name,list<person> friends) { person newperson=new person(); newperson.setname(name); newperson.setfullname(new fullname("zjj_first", "zjj_middle", "zjj_last")); newperson.setage(24); list<string> hobbies=new arraylist<string>(); hobbies.add("篮球"); hobbies.add("游泳"); hobbies.add("coding"); newperson.sethobbies(hobbies); map<string,string> clothes=new hashmap<string, string>(); clothes.put("coat", "nike"); clothes.put("trousers", "adidas"); clothes.put("shoes", "安踏"); newperson.setclothes(clothes); newperson.setfriends(friends); return newperson; }}
说明一下,上面的代码中
resultexporter.exportresult("json序列化性能", results, "count", "秒");
这个是我自己编写的将性能测试报告数据填充至echarts图,然后导出png图片的方法。
执行后的结果图:
从上面的测试结果可以看出,序列化次数比较小的时候,gson性能最好,当不断增加的时候到了100000,gson明细弱于jackson和fastjson, 这时候fastjson性能是真的牛,另外还可以看到不管数量少还是多,jackson一直表现优异。而那个json-lib简直就是来搞笑的。^_^
json反序列化性能基准测试@benchmarkmode(mode.singleshottime)@outputtimeunit(timeunit.seconds)@state(scope.benchmark)public class jsondeserializebenchmark { /** * 反序列化次数参数 */ @param({"1000", "10000", "100000"}) private int count; private string jsonstr; public static void main(string[] args) throws exception { options opt = new optionsbuilder() .include(jsondeserializebenchmark.class.getsimplename()) .forks(1) .warmupiterations(0) .build(); collection<runresult> results = new runner(opt).run(); resultexporter.exportresult("json反序列化性能", results, "count", "秒"); } @benchmark public void jsonlib() { for (int i = 0; i < count; i++) { jsonlibutil.json2bean(jsonstr, person.class); } } @benchmark public void gson() { for (int i = 0; i < count; i++) { gsonutil.json2bean(jsonstr, person.class); } } @benchmark public void fastjson() { for (int i = 0; i < count; i++) { fastjsonutil.json2bean(jsonstr, person.class); } } @benchmark public void jackson() { for (int i = 0; i < count; i++) { jacksonutil.json2bean(jsonstr, person.class); } } @setup public void prepare() { jsonstr="{"name":"邵同学","fullname":{"firstname":"zjj_first","middlename":"zjj_middle","lastname":"zjj_last"},"age":24,"birthday":null,"hobbies":["篮球","游泳","coding"],"clothes":{"shoes":"安踏","trousers":"adidas","coat":"nike"},"friends":[{"name":"小明","fullname":{"firstname":"xxx_first","middlename":"xxx_middle","lastname":"xxx_last"},"age":24,"birthday":null,"hobbies":["篮球","游泳","coding"],"clothes":{"shoes":"安踏","trousers":"adidas","coat":"nike"},"friends":null},{"name":"tony","fullname":{"firstname":"xxx_first","middlename":"xxx_middle","lastname":"xxx_last"},"age":24,"birthday":null,"hobbies":["篮球","游泳","coding"],"clothes":{"shoes":"安踏","trousers":"adidas","coat":"nike"},"friends":null},{"name":"陈小二","fullname":{"firstname":"xxx_first","middlename":"xxx_middle","lastname":"xxx_last"},"age":24,"birthday":null,"hobbies":["篮球","游泳","coding"],"clothes":{"shoes":"安踏","trousers":"adidas","coat":"nike"},"friends":null}]}"; } @teardown public void shutdown() { }}
执行后的结果图:
从上面的测试结果可以看出,反序列化的时候,gson、jackson和fastjson区别不大,性能都很优异,而那个json-lib还是来继续搞笑的。
以上就是几种几种主流json库的基本介绍,希望能对你有所帮助!
以上就是对比三家,才发现这款json库最好用的详细内容。
