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版本
FastJson22.0.52
FastJson1.2.83
Jackson2.17.2
Gson2.11.0
Hutool5.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序列化排名:

ToolScore百分制
FastJson213653527100
FastJson850282962.3
Jackson577983042.3
Gson12179348.9
Hutool4372933.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序列化排名:

ToolScore百分制
FastJson2236910100
Jackson21245789.7
FastJson17338673.2
Gson5093721.5
Hutool109284.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序列化排名:

ToolScore百分制
Jackson13398100
FastJson2965072.0
Gson583543.6
FastJson479135.8
Hutool10357.7

根据这个排名,我有两点想说:

  • Jackson,作为SpringBoot默认的JSON序列化工具,果然名不虚传。
  • Hutool,@所有人,大家看看项目中有没有使用Hutool-Json,如果有请到我办公室。
  1. 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
FastJson210011654586-14.6%13653527
FastJson51.35980216-29.7%8502829
Jackson27.43194855+162.3%1217934
Gson20.72415733+452.4%437293
Hutool7.3855421-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
FastJson2100691572+191.9%236910
FastJson71.6495493+185.8%173386
Jackson31.3216731-2.0%212457
Gson25.3174852+243.3%50937
Hutool5.537997-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
FastJson1009002+87.9%4791
FastJson295.08555-11.3%9650
Gson68.26141+5.2%5835
Jackson51.34614-65.6%13398
Hutool13.91252+20.9%1035

根据这个排名,我有三点想说:

  • FastJson2,青出于蓝而胜于蓝,但你没想到人家还留了一手。
  • FastJson,教会徒弟饿死师傅这个道理你是懂的。
  • Hutool,@所有人,大家看看项目中有没有使用Hutool-Json,如果有请到我办公室。

排行榜

Tool排名总分百分制SSMSBSSDSMDSBDS
FastJson2状元56710010010072.010010095.0
FastJson榜眼394.269.562.373.235.851.371.6100
Jackson探花34260.342.389.710027.431.351.3
Gson进士188.233.28.921.543.620.725.368.2
Hutool孙山42.27.43.24.67.77.35.513.9

图片

JSON解析性能排行榜