绝了,几款主流的 JSON 库性能对比!

本篇通过JMH(Oracle官方测试框架)来测试一下Java中几种常见的JSON解析库的性能。每次都在网上看到别人说什么某某库性能是如何如何的好,碾压其他的库。但是百闻不如一见,只有自己亲手测试过的才是最值得相信的。

JSON不管是在Web开发还是服务器开发中是相当常见的数据传输格式,一般情况我们对于JSON解析构造的性能并不需要过于关心,除非是在性能要求比较高的系统。

目前对于Java开源的JSON类库有很多种,下面我们取4个常用的JSON库进行性能测试对比,同时根据测试结果分析如果根据实际应用场景选择最合适的JSON库。

这4个JSON类库分别为:Gson,FastJson,Jackson,Json-lib

简单介绍

选择一个合适的JSON库要从多个方面进行考虑:

  1. 字符串解析成JSON性能

  2. 字符串解析成JavaBean性能

  3. JavaBean构造JSON性能

  4. 集合构造JSON性能

  5. 易用性

先简单介绍下四个类库的身份背景

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优点很多:

  1. Jackson 所依赖的jar包较少,简单易用。

  2. 与其他 Java 的 json 的框架 Gson 等相比,Jackson 解析大的 json 文件速度比较快。

  3. Jackson 运行时占用内存比较低,性能比较好

  4. Jackson 有灵活的 API,可以很容易进行扩展和定制。

目前最新版本是2.9.4,Jackson 的核心模块由三部分组成:

  1. jackson-core 核心包,提供基于”流模式”解析的相关 API,它包括 JsonPaser 和 JsonGenerator。Jackson 内部实现正是通过高性能的流模式 API 的 JsonGenerator 和 JsonParser 来生成和解析 json。

  2. jackson-annotations 注解包,提供标准注解功能;

  3. jackson-databind 数据绑定包,提供基于”对象绑定” 解析的相关 API( ObjectMapper )和”树模型” 解析的相关 API(JsonNode);基于”对象绑定” 解析的 API 和”树模型”解析的 API 依赖基于”流模式”解析的 API。

为什么Jackson的介绍这么长啊?因为它也是本人的最爱。

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省略@Overridepublic String toString() {StringBuilder str = new StringBuilder("Person [name=" + name + ", fullName=" + fullName + ", age="+ age + ", birthday=" + birthday + ", hobbies=" + hobbies+ ", clothes=" + clothes + "]\n");if (friends != null) {str.append("Friends:\n");for (Person f : friends) {str.append("\t").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@Overridepublic 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", "秒");}@Benchmarkpublic void JsonLib() {for (int i = 0; i < count; i++) {JsonLibUtil.bean2Json(p);}}@Benchmarkpublic void Gson() {for (int i = 0; i < count; i++) {GsonUtil.bean2Json(p);}}@Benchmarkpublic void FastJson() {for (int i = 0; i < count; i++) {FastJsonUtil.bean2Json(p);}}@Benchmarkpublic void Jackson() {for (int i = 0; i < count; i++) {JacksonUtil.bean2Json(p);}}@Setuppublic void prepare() {List<Person> friends=new ArrayList<Person>();friends.add(createAPerson("小明",null));friends.add(createAPerson("Tony",null));friends.add(createAPerson("陈小二",null));p=createAPerson("邵同学",friends);}@TearDownpublic 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图片的方法,具体代码我就不贴了,参考我的github源码。

执行后的结果图:

从上面的测试结果可以看出,序列化次数比较小的时候,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", "秒");}@Benchmarkpublic void JsonLib() {for (int i = 0; i < count; i++) {JsonLibUtil.json2Bean(jsonStr, Person.class);}}@Benchmarkpublic void Gson() {for (int i = 0; i < count; i++) {GsonUtil.json2Bean(jsonStr, Person.class);}}@Benchmarkpublic void FastJson() {for (int i = 0; i < count; i++) {FastJsonUtil.json2Bean(jsonStr, Person.class);}}@Benchmarkpublic void Jackson() {for (int i = 0; i < count; i++) {JacksonUtil.json2Bean(jsonStr, Person.class);}}@Setuppublic 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}]}";}@TearDownpublic void shutdown() {}
}

执行后的结果图:

从上面的测试结果可以看出,反序列化的时候,Gson、Jackson和FastJson区别不大,性能都很优异,而那个Json-lib还是来继续搞笑的。

作者:熊能
www.xncoding.com/2018/01/09/java/jsons.html往期推荐链表竟然比数组慢这么多?(动图+性能评测)局部变量竟然比全局变量快5倍?关注下方二维码,每一天都有干货!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/545961.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DWZ使用笔记

DWZ使用笔记 一、前言 在近期的一个项目中&#xff0c;引入了DWZ这个富client框架&#xff0c;算是一次尝试吧。期间也遇到不少问题&#xff0c;总算一一攻克了。特以此文记之。本人用的是dwz-ria-1.4.5Asp.net webform&#xff0c;写这篇笔记时最新版本号已经是1.4.6了。DWZ官…

阿里的简历多久可以投递一次?次数多了有没有影响?可以同时进行吗?

最近&#xff0c;无论是读者群&#xff0c;还是公众号后台&#xff0c;很多人都比较关注以下几个问题&#xff1a;阿里的简历是半年只能投递一次吗&#xff1f;阿里的面试可以多个部门同时进行吗&#xff1f;面试没过&#xff0c;又被系统捞起来了&#xff0c;我该怎么办&#…

记一次蚂蚁金服面试被虐经历

本文来自作者投稿&#xff0c;原作者&#xff1a;yes面试前的小姐姐来说说前不久蚂蚁金服一面的情况。说来也是巧合&#xff0c;当时在群里有位蚂蚁金服的小姐姐发了个内推&#xff0c;看了下JD感觉可以试试于是就私聊了小姐姐发简历内推了。我16年也就是大三上就开始实习了&am…

用python + openpyxl处理excel(07+)文档 + 一些中文处理的技巧

2019独角兽企业重金招聘Python工程师标准>>> 寻觅工具 确定任务之后第一步就是找个趁手的库来干活。 Python Excel上列出了xlrd、xlwt、xlutils这几个包&#xff0c;但是 它们都比较老&#xff0c;xlwt甚至不支持07版以后的excel它们的文档不太友好&#xff0c;都可…

Spring Boot 2.3.3 正式发布!

Spring Boot 2.3.3 稳定版已发布&#xff0c;可从 repo.spring.io 和 Maven Central 获取。<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.3.RELEASE</versio…

木板最优切割利润最大_最多进行K笔交易的股票最大买卖利润

木板最优切割利润最大This is a very popular interview problem to find maximum profit in stock buying and selling with at most K transactions. This problem has been featured in the interview rounds of Amazon. 这是一个非常受欢迎的面试问题&#xff0c;目的是在最…

[数据库]Oracle和mysql中的分页总结

Mysql中的分页物理分页•在sql查询时&#xff0c;从数据库只检索分页需要的数据•通常不同的数据库有着不同的物理分页语句•mysql物理分页&#xff0c;采用limit关键字•例如&#xff1a;检索11-20条 select * from user limit 10,10 ;* 每次只查询10条记录.当点击下一页的时候…

List 集合去重的 3 种方法

问题由来在实际开发的时候&#xff0c;我们经常会碰到这么一个困难&#xff1a;一个集合容器里面有很多重复的对象&#xff0c;里面的对象没有主键&#xff0c;但是根据业务的需求&#xff0c;实际上我们需要根据条件筛选出没有重复的对象。比较暴力的方法&#xff0c;就是根据…

C语言入门——排序

排序的方法有很多种比较常见的便为&#xff1a;冒泡排序、选择排序、插入排序、快速排序。 今天我们就围绕着四种排序来说&#xff0c;如果有兴趣的话可以去查找一下其他排序。 在排序这方面我们主要讨论&#xff1a; 稳定&#xff1a;如果a原本在b前面&#xff0c;而ab&…

【转】eclipse技巧1

2019独角兽企业重金招聘Python工程师标准>>> 俗话说的好啊&#xff0c;“工于利启事&#xff0c;必先善其器”&#xff0c;如果说你的编程功底是一个枪法的话&#xff0c;那么强大的eclipse就是android战士们最好的武器。 这里&#xff0c;我们来总结eclipse的使用技…

定时任务最简单的3种实现方法(超好用)

这是我的第 86 篇原创文章作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;定时任务在实际的开发中特别常见&#xff0c;比如电商平台 30 分钟后自动取消未支付的订单&#x…

C语言入门基础——Brute-Force算法

Brute-Force算法的基本思想是&#xff1a; 1) 从目标串s 的第一个字符起和模式串t的第一个字符进行比较&#xff0c;若相等&#xff0c;则继续逐个比较后续字符&#xff0c;否则从串s 的第二个字符起再重新和串t进行比较。 2) 依此类推&#xff0c;直至串t 中的每个字符依次和…

为什么劝你放弃Maven?看看Gradle的这些优点就知道了

相信使用Java的同学都用过Maven&#xff0c;这是一个非常经典好用的项目构建工具。但是如果你经常使用Maven&#xff0c;可能会发现Maven有一些地方用的让人不太舒服&#xff1a;Maven的配置文件是XML格式的&#xff0c;假如你的项目依赖的包比较多&#xff0c;那么XML文件就会…

css中的换行符_如何使用CSS防止项目列表中的换行符?

css中的换行符Introduction: 介绍&#xff1a; Dealing with various items in CSS sometimes pose very different problems. The problem could be anything, it could be related to positioning, arrangement, and whatnot, therefore all such kinds of problems require…

Java中的一些坑,汇总篇(2万字)

Photo Drew Farwell 文 | 常意1.前言

6款html5模板下载

http://www.100sucai.com/code/1316.htmlhttp://www.100sucai.com/code/1318.htmlhttp://www.100sucai.com/code/1310.htmlhttp://www.100sucai.com/code/1309.htmlhttp://www.100sucai.com/code/1303.htmlhttp://www.100sucai.com/code/1301.html转载于:https://blog.51cto.co…

高并发系统 3 大利器之缓存

引言随着互联网的高速发展&#xff0c;市面上也出现了越来越多的网站和app。我们判断一个软件是否好用&#xff0c;用户体验就是一个重要的衡量标准。比如说我们经常用的微信&#xff0c;打开一个页面要十几秒&#xff0c;发个语音要几分钟对方才能收到。相信这样的软件大家肯定…

QTimer与事件循环理解

问题分析 最近在使用QT的时候发现了某些问题&#xff0c;查阅资料最后总结一下。我起初是想用QT在界面还在加载时加载一副动画&#xff0c;然后动画下面有加载的滚动条代表时间&#xff0c;由于测试所以界面加载没写很多东西很快就加载完成了。我就想让他加载慢点我看看效果。…

MYSQL 数学运算符问题

背景&#xff1a; 在mysql中 ’stringA stringB 这种类型的操作&#xff0c;在mysql内部会自动转化为两个double 数进行运算。 -------------------------------------------------------------------------------------------------------------------------------- 例子&a…

面试系列第1篇:常见面试题和面试套路有哪些?

作者 | 面哥来源 | Java面试真题解析&#xff08;ID&#xff1a;aimianshi666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;面试是人生中为数不多的改变自身命运的途径之一&#xff0c;当然有效的准备面试也是人生中为数不多的低投入高回报的…