JSON解析工具对比:FastJson、Jackson、Gson、Hutool的性能评测与排行
JSON解析工具对比:FastJson、Jackson、Gson、Hutool的性能评测与排行
引言
在当今的项目中,JSON格式数据的使用越来越广泛,几乎无处不在。对JSON数据进行压缩不仅能显著降低存储和带宽成本,还能在数据格式转换时节省CPU计算资源。因此,JSON数据的转换速度直接影响接口响应时间以及系统吞吐量。为此,本文将对市面上主流的五种JSON解析工具——FastJson、FastJson2、Jackson、Gson 和 Hutool-JSON,利用JAVA基准测试对小、中、大JSON的序列化和反序列化进行六项指标的测试,最后提供一个性能排行榜,希望能为您在选择JSON工具时提供参考。
准备工作
2.1 JMH基准测试
在进行代码性能测试时,常见的简单方法是记录代码执行前后的时间差。然而,这种方法的准确性受到多种因素的影响,可能导致测试结果不稳定。为确保测试的准确性,本次使用了JMH(Java Microbenchmark Harness)
工具,它是由OpenJDK/Oracle
维护的,旨在帮助开发人员编写可靠的基准测试并规避常见误区。使用JMH
进行的测试结果具备更高的说服力。
添加JMH Maven
依赖:
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.36</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.36</version>
</dependency>
JMH测试代码:
@State(Scope.Thread)
public class HelloBenchmark {
@Benchmark
public void testMethod() throws InterruptedException {
Thread.sleep(10);
}
@Test
public void testBenchmark() throws Exception {
Options options = new OptionsBuilder()
.include(HelloBenchmark.class.getSimpleName())
.forks(1) //进程数
.threads(1) //线程数
.warmupIterations(1)
.measurementIterations(1)
.mode(Mode.Throughput)
.build();
new Runner(options).run();
}
}
JMH测试结果:
Benchmark Mode Score Units
testMethod thrpt 64.579 ops/s
2.2 测试JSON工具的版本
相同工具的不同版本在性能上可能存在显著差异。本文选取了当前主流版本进行测试,测试结果仅适用于以下版本:
Tool | 版本 |
---|---|
FastJson2 | 2.0.52 |
FastJson | 1.2.83 |
Jackson | 2.17.2 |
Gson | 2.11.0 |
Hutool | 5.8.23 |
以下为各工具版本对应的Maven依赖:
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.52</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-json</artifactId>
<version>5.8.23</version>
</dependency>
2.3 测试平台
测试结果受JDK版本和运行环境的影响,因此不同机器的得分差异可能显著。以下是我的测试环境配置:
- 硬件: MacBook Pro 16GB 13英寸 M2 2022 macOS Ventura 13.5.1 (22G90)
- JDK: Azul Zulu 17.0.8 - aarch64
- IDE: IntelliJ IDEA 2024.2 (Ultimate Edition)
2.4 测试代码
在测试中,我将针对 小JSON
、中JSON
和 大JSON
进行序列化和反序列化的性能评分。在此,我对小、中、大JSON的定义如下:
- 小JSON
在每个系统中,用户信息是最常见的,因此我选取用户详情接口返回的用户信息JSON作为小JSON进行测试,用户对象的定义如下:
@Data
public class User {
private Long id;
private String name;
private String trueName;
private Integer age;
private String sex;
private Date createTime;
}
- 中JSON
在实际项目中,除了获取用户详情接口外,获取列表接口也非常常见。一般分页返回的数据条数为10条或20条,因此我选取20条用户信息作为中JSON的测试数据,这种数据具备代表性。中JSON的数据定义如下:
private List<User> users;
@Setup
public void setup() {
users = new ArrayList<>();
IntStream.range(1, 20).forEach(x -> {
User user = new User();
user.setId(1L);
user.setName(RandomUtil.randomString("公众号:赵侠客",100));
user.setAge(29);
user.setSex("男");
user.setTrueName(RandomUtil.randomString("公众号:赵侠客",100));
user.setCreateTime(new Date());
users.add(user);
});
}
- 大JSON
在各个项目中,大JSON的定义各有不同。以博客系统为例,我认为大JSON可能是文章正文中的HTML富文本数据。因此在测试数据中,我选取公众号文章详情页的HTML富文本数据作为大JSON。大JSON对象的定义如下:
@Data
public class Article {
private Long id;
private String author;
private Long tenantId;
private String title;
private String subTitle;
private String htmlContent;
private Date publishTime;
}
@Setup
public void setup() throws IOException {
article = new Article();
article.setId(10000L);
article.setTenantId(10000L);
article.setAuthor("公众号:赵侠客");
article.setPublishTime(new Date());
article.setTitle(RandomUtil.randomString("主标题", 100));
article.setSubTitle(RandomUtil.randomString("副标题", 50));
article.setHtmlContent(new String(Files.readAllBytes(Paths.get("article.html"))));
}
大JSON部分数据内容
定义完小JSON
、中JSON
、大JSON
后,就可以使用JMH
进行基准测试,以下是小JSON序列化的测试代码:
@State(Scope.Thread)
public class SmallJsonSerialize {
private User user;
private ObjectMapper mapper;
private Gson gson;
@Setup
public void setup() {
user = new User();
user.setId(1L);
user.setName("赵侠客");
user.setAge(29);
user.setSex("男");
user.setTrueName("公众号");
user.setCreateTime(new Date());
mapper = new ObjectMapper();
gson = new Gson();
}
@TearDown
public void tearDown() {
user = null;
mapper = null;
gson = null;
}
@Benchmark
public void testFastJson() {
String json = JSON.toJSONString(user);
}
@Benchmark
public void testFast2Json() {
String json = com.alibaba.fastjson2.JSON.toJSONString(user);
}
@Benchmark
public void testHutoolJson() {
String json = JSONUtil.toJsonStr(user);
}
@Benchmark
public void testJackson() throws JsonProcessingException {
String json = mapper.writeValueAsString(user);
}
@Benchmark
public void testGson() {
String json = gson.toJson(user);
}
@Test
public void testBenchmark() throws Exception {
Options options = new OptionsBuilder()
.include(SmallJsonSerialize.class.getSimpleName())
.forks(1)
.threads(1)
.warmupIterations(1)
.measurementIterations(1)
.mode(Mode.Throughput)
.build();
new Runner(options).run();
}
}
JSON序列化测试
3.1 小JSON序列化测试
3.1.1 小JSON序列化跑分:
Benchmark Score Units
FastJson2 13653527.046 ops/s
FastJson 8502829.931 ops/s
Gson 1217934.274 ops/s
HutoolJson 437293.524 ops/s
Jackson 5779830.068 ops/s
从结果来看,小JSON的序列化非常快速,HTTP接口的响应时间通常在几十毫秒到几秒之间,因此对小JSON的序列化不会显著影响接口性能。如果您的项目中仅有小JSON的场景,那么选择工具时可以相对随意,重点可以放在业务逻辑上而无需过于纠结JSON工具的选择。然而,作为技术爱好者,我将对五种工具的得分进行排名,Score为JMH的跑分。
百分制:最大Score的得100分,其它为 100*(Score/最大值)
3.1.2 小JSON序列化排名:
Tool | Score | 百分制 |
---|---|---|
FastJson2 | 13653527 | 100 |
FastJson | 8502829 | 62.3 |
Jackson | 5779830 | 42.3 |
Gson | 1217934 | 8.9 |
Hutool | 437293 | 3.2 |
根据这个排名,我有两点想说:
- FastJson2,无敌是多么,多么寂寞。
- Hutool,@所有人,大家看看项目中有没有使用Hutool-Json,如果有请到我办公室。
3.2 中JSON序列化测试
3.2.1 中JSON序列化跑分:
Benchmark Score Units
FastJson2 236910.655 ops/s
FastJson 173386.528 ops/s
Gson 50937.391 ops/s
HutoolJson 10928.165 ops/s
Jackson 212457.203 ops/s
对于中JSON的序列化,得分明显下降,最差的Hutool每秒仅能序列化过万次,大约需要0.1毫秒才能完成一次JSON转换。如果接口中存在大量的中JSON序列化调用,将会对响应时间造成一定影响。
3.2.2 中JSON序列化排名:
Tool | Score | 百分制 |
---|---|---|
FastJson2 | 236910 | 100 |
Jackson | 212457 | 89.7 |
FastJson | 173386 | 73.2 |
Gson | 50937 | 21.5 |
Hutool | 10928 | 4.6 |
看到这个排名后,我有两点想说:
- FastJson2,无敌是多么,多么空虚。
- Hutool,@所有人,大家看看项目中有没有使用Hutool-Json,如果有请到我办公室。
3.3 大JSON序列化测试
3.3.1 大JSON序列化跑分:
Benchmark Score Units
FastJson2 9650.211 ops/s
FastJson 4791.032 ops/s
Gson 5835.649 ops/s
HutoolJson 1035.357 ops/s
Jackson 13398.324 ops/s
在大JSON的序列化中,Hutool的表现最差,每次序列化的时间已经达到1毫秒。我在PC上跑了相同的测试,结果如下:
Benchmark Score Units
Fast2Json 5788.067 ops/s
FastJson 2480.132 ops/s
Gson 2176.535 ops/s
HutoolJson 455.914 ops/s
Jackson 5276.439 ops/s
在Intel(R) Core(TM) i7-4790K CPU @ 4.00GHz上测试的结果显示,Hutool的执行时间最长,每次JSON序列化需要达到2毫秒。因此,大JSON解析的速度对我们的接口性能影响非常明显。
3.3.2 大JSON序列化排名:
Tool | Score | 百分制 |
---|---|---|
Jackson | 13398 | 100 |
FastJson2 | 9650 | 72.0 |
Gson | 5835 | 43.6 |
FastJson | 4791 | 35.8 |
Hutool | 1035 | 7.7 |
根据这个排名,我有两点想说:
- Jackson,作为SpringBoot默认的JSON序列化工具,果然名不虚传。
- Hutool,@所有人,大家看看项目中有没有使用Hutool-Json,如果有请到我办公室。
-
JSON反序列化测试
4.1 小JSON反序列化测试
4.1.1 小JSON反序列化跑分:
Benchmark Score Units
FastJson2 11654586.191 ops/s
FastJson 5980216.867 ops/s
Gson 2415733.238 ops/s
HutoolJson 855421.710 ops/s
Jackson 3194855.332 ops/s
4.1.2 小JSON反序列化排名:
Tool | 百分制 | SDS | 变化 | SS |
---|---|---|---|---|
FastJson2 | 100 | 11654586 | -14.6% | 13653527 |
FastJson | 51.3 | 5980216 | -29.7% | 8502829 |
Jackson | 27.4 | 3194855 | +162.3% | 1217934 |
Gson | 20.7 | 2415733 | +452.4% | 437293 |
Hutool | 7.3 | 855421 | -85.2% | 5779830 |
根据这个排名,我有四点想说:
- FastJson2,无敌是多么,多么寂寞。
- Jackson & Gson,相比于序列化,反序列化要快得多。
- FastJson & FastJson2,你们很强,但却输给了自己。
- Hutool,@所有人,大家看看项目中有没有使用Hutool-Json,如果有请到我办公室。
4.2 中JSON反序列化测试
4.2.1 中JSON反序列化跑分:
Benchmark Score Units
FastJson2 691572.756 ops/s
FastJson 495493.338 ops/s
Gson 174852.543 ops/s
HutoolJson 37997.839 ops/s
Jackson 216731.673 ops/s
4.2.2 中JSON反序列化排名:
Tool | 百分制 | MDS | 变化 | MS |
---|---|---|---|---|
FastJson2 | 100 | 691572 | +191.9% | 236910 |
FastJson | 71.6 | 495493 | +185.8% | 173386 |
Jackson | 31.3 | 216731 | -2.0% | 212457 |
Gson | 25.3 | 174852 | +243.3% | 50937 |
Hutool | 5.5 | 37997 | -25.4% | 50937 |
根据这个排名,我有三点想说:
- FastJson2,无敌是多么,多么空虚。
- FastJson2 & FastJson,不仅强大,还比自己序列化更快。
- Hutool,@所有人,大家看看项目中有没有使用Hutool-Json,如果有请到我办公室。
4.3 大JSON反序列化测试
4.3.1 大JSON反序列化跑分:
Benchmark Score Units
FastJson2 8555.106 ops/s
FastJson 9002.889 ops/s
Gson 6141.212 ops/s
HutoolJson 1252.990 ops/s
Jackson 4614.815 ops/s
4.3.2 大JSON反序列化排名:
Tool | 百分制 | BDS | 变化 | BS |
---|---|---|---|---|
FastJson | 100 | 9002 | +87.9% | 4791 |
FastJson2 | 95.0 | 8555 | -11.3% | 9650 |
Gson | 68.2 | 6141 | +5.2% | 5835 |
Jackson | 51.3 | 4614 | -65.6% | 13398 |
Hutool | 13.9 | 1252 | +20.9% | 1035 |
根据这个排名,我有三点想说:
- FastJson2,青出于蓝而胜于蓝,但你没想到人家还留了一手。
- FastJson,教会徒弟饿死师傅这个道理你是懂的。
- Hutool,@所有人,大家看看项目中有没有使用Hutool-Json,如果有请到我办公室。
排行榜
Tool | 排名 | 总分 | 百分制 | SS | MS | BS | SDS | MDS | BDS |
---|---|---|---|---|---|---|---|---|---|
FastJson2 | 状元 | 567 | 100 | 100 | 100 | 72.0 | 100 | 100 | 95.0 |
FastJson | 榜眼 | 394.2 | 69.5 | 62.3 | 73.2 | 35.8 | 51.3 | 71.6 | 100 |
Jackson | 探花 | 342 | 60.3 | 42.3 | 89.7 | 100 | 27.4 | 31.3 | 51.3 |
Gson | 进士 | 188.2 | 33.2 | 8.9 | 21.5 | 43.6 | 20.7 | 25.3 | 68.2 |
Hutool | 孙山 | 42.2 | 7.4 | 3.2 | 4.6 | 7.7 | 7.3 | 5.5 | 13.9 |
JSON解析性能排行榜