Java中几种常用JSON库的性能比较
上一篇文章介绍了Java性能测试框架JMH的用法,本文通过JMH测试了几种常见的Java JSON解析库的性能。每次看到别人在网上说某个库的性能有多好,我就碾压其他库。但是看到你听到的比看到你听到的要好。只有自己亲手测试过的才是最值得信赖的。
在Web开发和服务器开发中,JSON都是一种非常常见的数据传输格式。一般来说,我们不需要太关注JSON解析和构造的性能,除非在性能要求高的系统中。
目前,Java开源的JSON类库有很多种。我们以四个常用的JSON库进行性能测试对比,根据测试结果分析是否根据实际应用场景选择最适合的JSON库。
四个JSON类库分别是Gson、FastJson、Jackson和Json-lib。
简介
选择合适的JSON库要从多方面考虑:
将字符串解析为JSON性能字符串解析为JavaBean性能JavaBean构造JSON性能集合构造JSON性能易用性首先简单介绍下四个类库的身份背景
Gson
项目地址:https://github.com/google/gson
Gson是目前最通用的Json解析构件。Gson最初是谷歌为满足谷歌内部需求而开发的,但自2008年5月第一版发布以来,已经被许多公司或用户应用。Gson的应用主要包括两个转换函数:toJson和fromJson,这两个函数没有依赖性,不需要额外的jar,可以直接在JDK上运行。在使用这个对象转换之前,需要先创建对象类型及其成员,然后才能成功地将JSON字符串转换为相应的对象。只要类中有get和set方法,Gson就可以完全实现从json到bean或者bean到json的转换,这是JSON解析的一个神器。
使用
项目地址:https://github.com/alibaba/fastjson
Fastjson是一款用Java语言编写的高性能json处理器,由阿里巴巴开发。没有依赖,不需要异常,额外的jar,可以直接在JDK上运行。将Json从复杂类型的Bean转换为FastJson存在一些问题,可能导致Json转换出错,需要做引用。FastJson采用原创算法,将解析速度提升到极致,超越所有Json库。
杰克逊
项目地址:https://github.com/FasterXML/jackson
Jackson是一个广泛使用的Java开源框架,用于序列化和反序列化json。杰克逊社区比较活跃,更新速度也比较快。根据Github中的统计,Jackson是目前最流行的json解析器之一,Spring MVC中默认的json解析器是Jackson。
杰克逊有很多优点:
杰克逊依赖较少的罐子包装,并且易于使用。与Java中的Gson等其他json框架相比,Jackson解析大型json文件的速度更快。Jackson的运行时占用的内存更少,性能更好。Jackson拥有灵活的API,可以轻松扩展和定制。目前最新版本是2.9.4,Jackson的核心模块由三部分组成:
Jackson-core核心包,提供基于“流模式”解析的相关API,包括JsonPaser和JsonGenerator。Jackson的内部实现通过高性能流模式API的JsonGenerator和JsonParser生成和解析json。Jackson-annotations批注包,提供标准批注功能;Jackson-databind数据绑定包,提供基于“对象绑定”解析的相关API和基于“树模型”解析的相关API(JSON Node);基于“对象绑定”解析的API和基于“树模型”解析的API依赖于基于“流模式”解析的API。为什么杰克逊的介绍这么长?因为它也是我的最爱。
Json-lib
项目地址:http://json-lib.sourceforge.net/index.html
json-lib最开始的也是应用最广泛的数据解析工具json-lib不好的地方确实是依赖于很多第三方包,对于复杂类型的转换json-lib对于数据转换成豆还有缺陷,比如一个类里面会出现另一个类的目录或者地图集合json-lib从数据到豆的转换就会出现问题json-lib在功能和性能上面都不能满足现在互联网化的需求。
编写性能测试
接下来开始编写这四个库的性能测试代码。
添加专家依赖
当然首先是添加四个库的专家依赖,公平起见,我全部使用它们最新的版本:
!-Json libs-依赖组idnet。SF。JSON-lib/组id artifactIdjson-lib/artifactId版本2.4/版本分类器JDK 15分类器/dependency dependency groupIdcom.google.code.gson/groupId artifactIdgson/artifactId版本2 .8 .2/版本/dependency dependency groupIdcom.alibaba/groupId artifactIdfastjson/artifactId版本1 .2 .46/版本/dependency依赖项依赖项组idcom。fasterxml。杰克逊。核心/组id artifactIdjackson-data bind/artifactId四个库的工具类
FastJsonUtil.java
公共类FastJsonUtil {公共静态String bean 2 JSON(Object obj){ return JSON。to jsonstring(obj);}公共静态T T js2 bean(String jsonStr,class T objClass){ return JSON。parseobject(jsonStr,Objclass);}}GsonUtil.java
公共类GsonUtil {私有静态Gson gson=new GsonBuilder().create();公共静态字符串bean 2 JSON(Object obj){ return gson。到JSON(obj);}公共静态T T js2 bean(String jsonStr,class T objClass){ return gson。fromjson(jsonStr,Objclass);}公共静态String jsonFormatter(String uglyJsonStr){ Gson Gson=new Gson builder().setPrettyPrinting().create();JsonParser jp=new JsonParser();JsonElement je=jp。解析(uglyJsonStr);返回gson。致JSON(je);}}JacksonUtil.java
公共类杰克逊努蒂尔私有静态对象映射器=新对象映射器();公共静态字符串bean 2 JSON(Object obj){ try { return mapper。writevalueasstring(obj);} catch(JsonProcessingException e){ e . print stack trace();返回null} }公共静态T T js2 bean(String jsonStr,class T objClass){ try { return mapper。readvalue(jsonStr,Objclass);} catch(IOexception e){ e . print stack trace();返回null } } } JsonLibUtil.java
公共类JsonLibUtil {公共静态字符串bean 2 JSON(对象obj){ JSON对象JSON对象=JSON对象。从对象;返回JSonobject。ToString();} @SuppressWarnings(未选中)公共静态T T js2 bean(String jsonStr,class T objClass){ return(T)JSON对象。toban(JSON对象。from对象(jsonStr),Objclass);}}准备模型类
这里我写一个简单的人类,同时属性有日期、列表、地图和自定义的类全名,最大程度模拟真实场景。
公共类人{私有字符串名称;私有全名全名;私人互联网时代;私人约会生日;私人列表字符串爱好;私映射弦,弦衣;私人列表人朋友;//getter/setter省略@将公共字符串重写为字符串(){ StringBuilder str=new StringBuilder(' Person[name=' name '、fullName=' fullName '、age=' age '),生日='生日、爱好='嗜好、衣服='衣服]\ n ');如果(朋友!=null){ str。追加(' Friends 3360 \ n ');对于(人f :朋友){ str。追加(' \ t ').追加(f);} }返回字符串。ToString();} }公共类全名{私有字符串名字;私有字符串中间名私有字符串姓氏;公共全名(){ }公共全名(字符串名字,字符串中间名,字符串姓氏){这个。名字=名字;middleName=middleNamethis。姓氏=姓氏;} //省略吸气剂和setter @ Override public String to String(){ return '[名字='名字',中间名=' middleName ',姓氏='姓氏']';}}JSON序列化性能基准测试
@基准模式(模式单线时间)@输出时间单位(时间单位。秒)@状态(范围基准测试)公共类JsonSerializeBenchmark { /** *序列化次数参数*/@Param({'1000 ',' 10000 ',' 100000'})私有(同Internationalorganizations)国际组织计数;私人p;公共静态void main(字符串[]参数)引发异常{ Options opt=new OptionsBuilder().包括(jsonserializebenchmark。上课。getsimplename()).叉子(1)。warmupIterations(0).build();CollectionRunResult结果=新的跑步者.run();结果导出器。导出结果(' JSON序列化性能,结果,"计数"秒');} @ Benchmark public void JsonLib(){ for(int I=0;我数;I){ jsonlibtil。bean 2 JSON(p);} } @ Benchmark public void Gson(){ for(int I=0;我数;I){ gsonutil。bean 2 JSON(p);} } @ Benchmark public void FastJson(){ for(int I=0;我数;I){ fastjsonutil。bean 2 JSON(p);} } @ Benchmark public void Jackson(){ for(int I=0;我数;我){杰克逊努蒂尔。bean 2 JSON(p);} } @ Setup public void prepare(){ list person friends=new ArrayList person();friends.add(createAPerson('小明,null));朋友。add(createAPerson(' Tony ',null));friends.add(createAPerson('陈小二,null));p=createAPerson('邵同学,朋友);} @ discordown public void shut down(){ } private Person create aperson(字符串名称,列表人好友){ Person new Person=new Person();newPerson.setName(名称);newPerson.setFullName(新全名(' zjj_first ',' zjj_middle ',' zjj _ last ');新人。setage(24);列表字符串爱好=new ArraylistString();"爱好。添加("篮球');"爱好。添加("游泳');爱好。添加('编码');newPerson.setHobbies爱好(兴趣爱好);映射字符串衣服=new HashMapString,String();衣服。'放('大衣,‘Nike’);衣服。'放('裤子、‘阿迪达斯’;衣服。穿上(鞋子)安踏');new person . set衣服衣服(衣服);newPerson.setFriends(朋友);返回newPerson}}说明一下,上面的代码中
结果导出器。导出结果(' JSON序列化性能,结果,"计数"秒');这个是我自己编写的将性能测试报告数据填充至展示图,然后导出巴布亚新几内亚图片的方法,具体代码我就不贴了,参考我的开源代码库源码。
执行后的结果图:
从上面的测试结果可以看出,序列化次数比较小的时候,Gson性能最好,当不断增加的时候到了100000,Gson明细弱于杰克逊和FastJson,这时候使用性能是真的牛,另外还可以看到不管数量少还是多杰克逊一直表现优异。而那个Json-lib简直就是来搞笑的。^_^
数据反序列化性能基准测试
@基准模式(模式单线时间)@输出时间单位(时间单位。秒)@状态(范围基准测试)公共类jsondserializebenchmark {/* * *反序列化次数参数*/@Param({'1000 ',' 10000 ',' 100000'})私有(同Internationalorganizations)国际组织计数;私有字符串jsonStr公共静态void main(字符串[]参数)引发异常{ Options opt=new OptionsBuilder().包括(jsondserializebenchmark。上课。getsimplename()).叉子(1)。warmupIterations(0).build();CollectionRunResult结果=新的跑步者.run();结果导出器。导出结果(' JSON反序列化性能,结果,"计数"秒');} @ Benchmark public void JsonLib(){ for(int I=0;我数;I){ jsonlibtil。js 2 bean(jsonStr,person。类);} } @ Benchmark public void Gson(){ for(int I=0;我数;I){ gsonutil。js2 bean(jsonStr,person。类);} } @ Benchmark public void FastJson(){ for(int I=0;我数;I){ fastjsonutil。js 2 bean(jsonStr,person。类);} } @ Benchmark public void Jackson(){ for(int I=0;我数;我){杰克逊特尔。js2 bean(jsonStr,person。类);} } @ Setup public void prepare(){ jsonStr=' { \ ' name ' : \ '邵同学\ ',\ '全名' : { \ '名字' : ' zjj _ first \ ',\ ' middleName \ ' : \ ' zjj _ middle \ ',\ ' lastName \ ' : \ ' zjj _ last \ ' },\ ' age \ ' :24,\ '生日' :null,'兴趣爱好' :[\ '篮球\',\'游泳\ ',\ '编码\'],\ '衣服' :{\ '鞋子' :\ '安踏\ ',\ '裤子' : '阿迪达斯\ ',\ '外套' : '耐克\'},\ '朋友' :[{\ '姓名' :\ '小明\ ',\ '全名' : { \ '名字' : ' XXX _ first \ ',\ '中间名' : \ ' xxx _ middle \ ',\ '姓氏' : \ ' xxx _ last \ ' },\ '年龄' :24,\ '生日' :null,'兴趣爱好' :[\ '篮球\',\'游泳\ ',\ '编码\'],\ '衣服' :{\ '鞋子' :\ '安踏\ ',\ '裤子: \ ' adidas \ ',\ '外套: \ ' Nike \ ' },\ '朋友:null ',{\ '姓名:“托尼”全名' :{\ '名字: \ ' xxx _ first \ ',\ '中间名: \ ' xxx _ middle \ ',\ '姓氏: \ ' xxx _ last \ ' },\ '年龄篮球\',\'游泳\ ',\ '编码\'],\ '衣服' :{\ '鞋子' :\ '安踏\ ',\ '裤子' : '阿迪达斯\ ',\ '外套' : '耐克\'},\ '朋友:null},{\ '姓名' :\ '陈小二\ ',\ '全名' : { \ 名' : ' XXX _ first \ ',\ ' middleName \ ' : \ ' xxx _ middle \ ',\ ' lastName \ ' : \ ' xxx _ last \ ' },\ ' age \ ' :24,\ '生日' :null,'兴趣爱好' :[\ '篮球\',\'游泳\ ',\ '编码\'],\ '衣服' :{\ '鞋子' :\ '安踏\ ',\ '裤子: \ ' adidas \ ',\ '外套: \ ' Nike \ ' },\ '朋友: null }]} '; } @拆卸公共无效关机(){ }}执行后的结果图:
从上面的测试结果可以看出,反序列化的时候,Gson,杰克逊和使用区别不大,性能都很优异,而那个Json-lib还是来继续搞笑的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
版权声明:Java中几种常用JSON库的性能比较是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。