Java四大常用JSON解析工具性能对比(Hutool、Fastjson2、Gson与Jackson)

 更新时间:2025年05月20日 08:50:42   作者:不掉头发的阿水  
JSON 是现代软件开发中常用的数据交换格式,尤其在微服务和前后端分离的架构中更是必不可少,本文将对 Java 中四大主流 JSON 解析库进行性能测试和对比分析,希望对大家有所帮助

1. 引言

JSON 是现代软件开发中常用的数据交换格式,尤其在微服务和前后端分离的架构中更是必不可少。

本文将对 Java 中四大主流 JSON 解析库——Hutool、Fastjson2、Gson 和 Jackson 进行性能测试和对比分析,通过实测 20 万条数据解析,揭示各库在批量和逐条处理中的表现。

测试结果仅供参考!!! 请多次测试再抉择

2. 环境与依赖

2.1 环境信息

操作系统:Window11

JDK 版本:jdk1.8.0_281

CPU :  AMD Ryzen 9 7945HX

内存:32GB

2.2 Maven依赖

在项目的 pom.xml 文件中引入以下依赖:

      <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.10.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
            <version>2.0.52</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.14.2</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.35</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

3. 测试代码

3.1 数据模型

定义一个简单的实体对象:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
 
/**
 * @author 阿水
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Variable {
    private int id;
    private String name;
    private double value;
    private String description;
    private String type;
}

3.2 测试数据生成

模拟 20 万条数据用于测试:

  // 生成测试数据
    public static List<Variable> generateData(int size) {
        List<Variable> list = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            Variable data = new Variable();
            data.setId(i);
            data.setName("Name" + i);
            data.setValue(Math.random() * 1000);
            data.setDescription(IdUtil.fastSimpleUUID());
            data.setType(IdUtil.fastSimpleUUID()+i);
            list.add(data);
        }
        return list;
    }

3.3 四大库序列化与反序列化测试

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
 
/**
 * @description: JSON 序列化、解析性能测试
 * @author 阿水
 */
@Slf4j
public class JsonBenchmarkTest {
    //数据总条数
    public static int dataSize = 200000;
    //测试次数
    public static  int iterations = 10;
 
    public static void main(String[] args) throws Exception {
        // 生成测试数据
        List<Variable> testData = generateData(dataSize);
        log.info("测试数据总条数为: {} 条", dataSize);
        log.info("以下测试结果均为进行 {} 次计算之后,耗费时间取平均值计算得出。", iterations);
        // 序列化测试
        String jsonString = serializationTest(testData);
        log.info("JSON 数据总大小为: {} 字节", jsonString.length());
 
        // 批量解析测试
        log.info("===== 使用批量解析 JSON(即解析集合API)=====");
        batchParseTest(jsonString);
 
        // 单条解析测试
        log.info("===== 循环遍历逐个解析 JSON API =====");
        singleParseTest(jsonString);
 
        // 单条解析并插入集合测试
        log.info("===== 循环遍历逐个解析 JSON并插入集合 API=====");
        singleParseAndAddListTest(jsonString);
    }
    // 生成测试数据
    public static List<Variable> generateData(int size) {
        List<Variable> list = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            Variable data = new Variable();
            data.setId(i);
            data.setName("Name" + i);
            data.setValue(Math.random() * 1000);
            data.setDescription(IdUtil.fastSimpleUUID());
            data.setType(IdUtil.fastSimpleUUID()+i);
            list.add(data);
        }
        return list;
    }
    /**
     * 序列化测试
     */
    private static String serializationTest(List<Variable> testData) throws Exception {
        String jsonResult = null;
        // Hutool
        long hutoolTotal = 0;
        for (int i = 0; i < iterations; i++) {
            long start = System.currentTimeMillis();
            String hutoolJson = JSONUtil.toJsonStr(testData);
            long end = System.currentTimeMillis();
            hutoolTotal += (end - start);
            if (i == 0) jsonResult = hutoolJson; // 保存结果
        }
        log.info("HuTool 序列化平均耗时: {} ms", hutoolTotal / iterations);
 
        // Fastjson2
        long fastjsonTotal = 0;
        for (int i = 0; i < iterations; i++) {
            long start = System.currentTimeMillis();
            String fastjsonJson = JSON.toJSONString(testData);
            long end = System.currentTimeMillis();
            fastjsonTotal += (end - start);
        }
        log.info("Fastjson2 序列化平均耗时: {} ms", fastjsonTotal / iterations);
 
        // Gson
        Gson gson = new Gson();
        long gsonTotal = 0;
        for (int i = 0; i < iterations; i++) {
            long start = System.currentTimeMillis();
            String gsonJson = gson.toJson(testData);
            long end = System.currentTimeMillis();
            gsonTotal += (end - start);
        }
        log.info("Gson 序列化平均耗时: {} ms", gsonTotal / iterations);
 
        // Jackson
        ObjectMapper objectMapper = new ObjectMapper();
        long jacksonTotal = 0;
        for (int i = 0; i < iterations; i++) {
            long start = System.currentTimeMillis();
            String jacksonJson = objectMapper.writeValueAsString(testData);
            long end = System.currentTimeMillis();
            jacksonTotal += (end - start);
        }
        log.info("Jackson 序列化平均耗时: {} ms", jacksonTotal / iterations);
 
        return jsonResult;
    }
 
    /**
     * 批量解析测试
     */
    private static void batchParseTest(String jsonString) throws Exception {
        // Hutool
        long hutoolTotal = 0;
        for (int i = 0; i < iterations; i++) {
            long start = System.currentTimeMillis();
            List<Variable> result = JSONUtil.toList(JSONUtil.parseArray(jsonString), Variable.class);
            long end = System.currentTimeMillis();
            hutoolTotal += (end - start);
        }
        log.info("HuTool 批量解析平均耗时: {} ms", hutoolTotal / iterations);
 
        // Fastjson2
        long fastjsonTotal = 0;
        for (int i = 0; i < iterations; i++) {
            long start = System.currentTimeMillis();
            List<Variable> result = JSON.parseArray(jsonString, Variable.class);
            long end = System.currentTimeMillis();
            fastjsonTotal += (end - start);
        }
        log.info("Fastjson2 批量解析平均耗时: {} ms", fastjsonTotal / iterations);
 
        // Gson
        Gson gson = new Gson();
        long gsonTotal = 0;
        for (int i = 0; i < iterations; i++) {
            long start = System.currentTimeMillis();
            List<Variable> result = gson.fromJson(jsonString, new TypeToken<List<Variable>>() {}.getType());
            long end = System.currentTimeMillis();
            gsonTotal += (end - start);
        }
        log.info("Gson 批量解析平均耗时: {} ms", gsonTotal / iterations);
 
        // Jackson
        ObjectMapper objectMapper = new ObjectMapper();
        long jacksonTotal = 0;
        for (int i = 0; i < iterations; i++) {
            long start = System.currentTimeMillis();
            List<Variable> result = objectMapper.readValue(jsonString, new TypeReference<List<Variable>>() {});
            long end = System.currentTimeMillis();
            jacksonTotal += (end - start);
        }
        log.info("Jackson 批量解析平均耗时: {} ms", jacksonTotal / iterations);
    }
 
    /**
     * 单条解析测试
     */
    private static void singleParseTest(String jsonString) throws Exception {
        List<String> messageList = JSON.parseArray(jsonString, Variable.class).stream()
                .map(JSON::toJSONString)
                .collect(Collectors.toList());
        // Hutool
        long hutoolTotal = 0;
        for (int i = 0; i < iterations; i++) {
            long start = System.currentTimeMillis();
            for (String msg : messageList) {
                Variable v = JSONUtil.toBean(msg, Variable.class);
            }
            long end = System.currentTimeMillis();
            hutoolTotal += (end - start);
        }
        log.info("HuTool 单条解析平均耗时: {} ms", hutoolTotal / iterations);
 
        // Fastjson2
        long fastjsonTotal = 0;
        for (int i = 0; i < iterations; i++) {
            long start = System.currentTimeMillis();
            for (String msg : messageList) {
                Variable v = JSON.parseObject(msg, Variable.class);
            }
            long end = System.currentTimeMillis();
            fastjsonTotal += (end - start);
        }
        log.info("Fastjson2 单条解析平均耗时: {} ms", fastjsonTotal / iterations);
 
        // Gson
        Gson gson = new Gson();
        long gsonTotal = 0;
        for (int i = 0; i < iterations; i++) {
            long start = System.currentTimeMillis();
            for (String msg : messageList) {
                Variable v = gson.fromJson(msg, Variable.class);
            }
            long end = System.currentTimeMillis();
            gsonTotal += (end - start);
        }
        log.info("Gson 单条解析平均耗时: {} ms", gsonTotal / iterations);
 
        // Jackson
        ObjectMapper objectMapper = new ObjectMapper();
        long jacksonTotal = 0;
        for (int i = 0; i < iterations; i++) {
            long start = System.currentTimeMillis();
            for (String msg : messageList) {
                Variable v = objectMapper.readValue(msg, Variable.class);
            }
            long end = System.currentTimeMillis();
            jacksonTotal += (end - start);
        }
        log.info("Jackson 单条解析平均耗时: {} ms", jacksonTotal / iterations);
    }
    /**
     * 循环遍历单条解析并插入集合测试
     */
    /**
     * 循环遍历单条解析并插入集合测试 (平均耗时计算)
     */
    static void singleParseAndAddListTest(String jsonString) throws Exception {
        // 转换为模拟 MQ 消息体
        List<String> messageList = JSON.parseArray(jsonString, Variable.class).stream()
                .map(JSON::toJSONString) // 将每个对象转为 JSON 字符串模拟单条消息
                .collect(Collectors.toList());
 
        // 平均耗时变量定义
        double hutoolTotalTime = 0;
        double fastjsonTotalTime = 0;
        double gsonTotalTime = 0;
        double jacksonTotalTime = 0;
 
        // 循环 10 次计算平均耗时
        for (int i = 0; i < iterations; i++) {
 
            // 1. Hutool JSONUtil 单条解析
            List<Variable> hutoolList = new ArrayList<>();
            long hutoolStart = System.currentTimeMillis();
            for (String msg : messageList) {
                Variable v = JSONUtil.toBean(msg, Variable.class);
                hutoolList.add(v); // 将对象存入集合
            }
            long hutoolEnd = System.currentTimeMillis();
            hutoolTotalTime += (hutoolEnd - hutoolStart);
 
            // 2. Fastjson2 单条解析
            List<Variable> fastjsonList = new ArrayList<>();
            long fastjsonStart = System.currentTimeMillis();
            for (String msg : messageList) {
                Variable v = JSON.parseObject(msg, Variable.class);
                fastjsonList.add(v);
            }
            long fastjsonEnd = System.currentTimeMillis();
            fastjsonTotalTime += (fastjsonEnd - fastjsonStart);
 
            // 3. Gson 单条解析
            List<Variable> gsonList = new ArrayList<>();
            Gson gson = new Gson();
            long gsonStart = System.currentTimeMillis();
            for (String msg : messageList) {
                Variable v = gson.fromJson(msg, Variable.class);
                gsonList.add(v);
            }
            long gsonEnd = System.currentTimeMillis();
            gsonTotalTime += (gsonEnd - gsonStart);
 
            // 4. Jackson 单条解析
            List<Variable> jacksonList = new ArrayList<>();
            ObjectMapper objectMapper = new ObjectMapper();
            long jacksonStart = System.currentTimeMillis();
            for (String msg : messageList) {
                Variable v = objectMapper.readValue(msg, Variable.class);
                jacksonList.add(v);
            }
            long jacksonEnd = System.currentTimeMillis();
            jacksonTotalTime += (jacksonEnd - jacksonStart);
        }
 
        // 输出平均耗时结果
        log.info("HuTool 单条解析并存入集合平均耗时: {} ms", hutoolTotalTime / iterations);
        log.info("Fastjson2 单条解析并存入集合平均耗时: {} ms", fastjsonTotalTime / iterations);
        log.info("Gson 单条解析并存入集合平均耗时: {} ms", gsonTotalTime / iterations);
        log.info("Jackson 单条解析并存入集合平均耗时: {} ms", jacksonTotalTime / iterations);
    }
 
}

4.结果分析

20W条数据、31098673字节测试结果分析(仅供参考 仅供参考 仅供参考 !!!)

库名称序列化+反序列化总耗时性能排名
Fastjson2110ms左右第一名
Jackson170ms左右第二名
Gson210ms左右第三名
Hutool1800ms左右第四名

5. 性能分析与总结

测试结果分析

1.Fastjson2

  • 性能表现: 测试结果中,无论是批量解析、逐条解析还是逐条解析并插入集合,它的速度都是最快的(30ms、39ms、39.8ms)。
  • 特性优势: 支持复杂对象结构解析,API 设计简洁高效,并修复了旧版 Fastjson 的反序列化漏洞,安全性更高。
  • 适用场景: 高并发、大数据量处理及性能敏感型应用场景。

2.Hutool

  • 性能表现: 表现最慢,尤其在批量解析(637ms)和逐条解析(589ms)中远落后于其他库。
  • 特性优势: API 优雅轻便,开发效率高,但性能瓶颈明显,不适合超大规模数据解析。
  • 适用场景: 适合中小规模项目的快速开发,便捷性优先于性能要求的场合。

3.Jackson

  • 性能表现: 表现较优,解析速度仅次于 Fastjson2(78ms、101ms、99.8ms),兼顾性能与功能复杂性。
  • 特性优势: 支持复杂 Java 对象和自定义配置,兼容性强,适合复杂数据结构映射需求。
  • 适用场景: 企业级应用、大型复杂系统开发及对灵活性要求高的项目。

4.Gson

  • 性能表现: 性能优于 Hutool,但低于 Fastjson2 和 Jackson(93ms、119ms、119.5ms)。
  • 特性优势: API 简单直观,开发成本低,但在大数据量或高并发处理时性能表现不够理想。
  • 适用场景: 小规模数据解析需求,或对性能要求不高的任务。

6. 推荐选择

求类型推荐库适用场景描述
性能优先Fastjson2在所有测试场景中速度最快,适合高性能和高并发场景,适合日志分析、大数据处理和消息队列数据解析等应用
轻量便捷Hutool更适合中小规模项目的快速开发,虽然性能较低,但 API 优雅轻便,适合便捷性优先的场合
功能复杂需求Jackson兼顾性能与灵活性,支持复杂数据结构和自定义配置,适合大型企业级应用或复杂对象映射需求
简单解析需求GsonAPI 简洁易用,适合小规模数据解析任务,学习成本低,但不适合大数据和高并发需求

7. 结论与建议

Fastjson2:

  • 性能最高,适合高并发与大数据处理需求。
  • 安全性较高,是性能敏感应用的首选。

Hutool:

  • 开发便捷但性能较低,适合中小规模项目。
  • 如果对开发效率要求高且数据量适中,可以选择它。

Jackson:

  • 性能与灵活性兼顾,适合复杂对象和企业级系统。
  • 面向需要自定义解析规则的场景表现更出色。

Gson:

  • 简单易用但性能低于 Fastjson2 和 Jackson。
  • 适合小型项目或对性能要求不高的场合。

注意事项

  • 安全性: Fastjson2 安全性最佳,其他库需关注版本更新,以避免反序列化漏洞。
  • 兼容性: Jackson 在跨平台兼容性和复杂结构处理方面表现更佳。
  • 性能评估: 项目正式使用前,应基于实际生产环境进行更大规模的性能测试和压力测试。

仅当前测试数据明确显示:

  • Fastjson2 性能最佳,适合高性能需求。
  • Hutool 性能最慢,更适合便捷开发而非大规模数据解析。
  • Jackson 在性能和灵活性之间取得平衡,适合复杂应用场景。
  • Gson 表现优于 Hutool,但略逊于 Fastjson2 和 Jackson,适合轻量级需求。

到此这篇关于Java四大常用JSON解析工具性能对比(Hutool、Fastjson2、Gson与Jackson)的文章就介绍到这了,更多相关Java解析JSON内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java构造器 默认构造方法及参数化构造方法

    java构造器 默认构造方法及参数化构造方法

    构造器也叫构造方法、构造函数,是一种特殊类型的方法,负责类中成员变量(域)的初始化。构造器的用处是在创建对象时执行初始化,当创建一个对象时,系统会为这个对象的实例进行默认的初始化,下面文章将进入讲解,需要的朋友可以参考下
    2021-10-10
  • 深入理解Spring bean加载顺序

    深入理解Spring bean加载顺序

    在默认配置下,SpringBean的加载顺序主要受到Bean定义顺序、依赖关系和生命周期回调方法的影响,本文就来了解一下Spring bean加载顺序,感兴趣的同学可以学习
    2024-10-10
  • SpringBoot+SpringSecurity实现基于真实数据的授权认证

    SpringBoot+SpringSecurity实现基于真实数据的授权认证

    Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架,Spring Security主要做两个事情,认证、授权。这篇文章主要介绍了SpringBoot+SpringSecurity实现基于真实数据的授权认证,需要的朋友可以参考下
    2021-05-05
  • Spring Boot集成LiteFlow规则引擎的详细过程

    Spring Boot集成LiteFlow规则引擎的详细过程

    本文详细介绍了如何在Spring Boot应用程序中集成LiteFlow规则引擎,并探讨如何使用LiteFlow库来实现业务流程的规则处理,将通过具体的示例来展示如何在Spring Boot应用程序中配置和使用LiteFlow规则引擎,以提高系统的灵活性和可维护性,感兴趣的朋友跟随小编一起看看吧
    2024-07-07
  • MyBatis自定义类型转换器实现加解密

    MyBatis自定义类型转换器实现加解密

    这篇文章主要介绍了MyBatis自定义类型转换器实现加解密的相关资料,需要的朋友可以参考下
    2016-07-07
  • java解析xml之dom4j解析xml示例分享

    java解析xml之dom4j解析xml示例分享

    DOM4J具有性能优异、功能强大和极端易用使用的特点,只要懂得DOM基本概念,就可以通过dom4j的api文档来解析xml,dom4j是一套开源的api。实际项目中,往往选择dom4j来作为解析xml的利器
    2014-01-01
  • Java反射的定义和用法详解

    Java反射的定义和用法详解

    Java中的反射是指在程序运行时动态地获取和操作类、方法、属性等元素的能力。它使得我们可以在程序运行时获取一个类的信息,并对其进行操作,需要的朋友可以参考下
    2023-05-05
  • java集合Collection常用方法解读

    java集合Collection常用方法解读

    这篇文章主要介绍了java集合Collection常用方法解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Java中将List列表转换为字符串的三种方法

    Java中将List列表转换为字符串的三种方法

    这篇文章主要介绍了如何在 Java中将List 转换为 String,接下来使用Java 8 Streams Collectors api和String.join()方法将带有逗号分隔符或自定义分隔符的集合转换为字符串,需要的朋友可以参考下
    2025-04-04
  • Java 实战项目锤炼之医院门诊收费管理系统的实现流程

    Java 实战项目锤炼之医院门诊收费管理系统的实现流程

    读万卷书不如行万里路,只学书上的理论是远远不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用java+html+jdbc+mysql实现一个医院门诊收费管理系统,大家可以在过程中查缺补漏,提升水平
    2021-11-11

最新评论