JSON 序列化框架性能横评:Jackson vs Gson vs Fastjson2 vs Moshi——不只是快慢

引言

选 JSON 库这件事,团队里的争论从来没停过:新同事看博客说“Fastjson 快”,架构组说“Fastjson 有漏洞史别碰”,做 Android 的同学说“Gson 就够了”,玩 Kotlin 的说“Moshi 才是正解”。各说各的理,谁也说服不了谁——因为大多数对比文章只跑了“快慢”一个维度,而真实选型要考虑六件事

这次我们认真做了一轮横评:四个框架(Jackson 2.17 / Gson 2.11 / Fastjson2 2.0.53 / Moshi 1.15)在同一个 Spring Boot 项目里,同一台机器、同一批数据、同一套 JMH 口径,跑序列化吞吐、反序列化速度、内存占用、特性支持、安全性、社区活跃度六个维度。先给结论——和许多人拍脑袋的印象一致又略有出入:

Jackson 是全能王:性能第一梯队、生态无可替代、Spring 默认集成;Fastjson2 性能确实最强,但安全包袱要用工程手段兜住;Gson 胜在轻量和零学习成本,简单场景够用;Moshi 是 Kotlin 世界的答案。

下面逐维度展开数据和依据。


一、评测设计:先立规矩,再谈数据

1.1 环境与口径

配置
硬件Apple M2 Pro(JMH 跑全核)/ 另在 4C8G Linux 云主机复核
JDKOpenJDK 21,-XX:+UseZGC(云主机用 G1 复核无结论性差异)
框架版本Jackson 2.17.2 / Gson 2.11.0 / Fastjson2 2.0.53 / Moshi 1.15.1
测试对象三类典型 POJO:嵌套订单对象(含 List、BigDecimal、日期)、扁平 DTO、10 字段中型对象
数据量单次调用 100 对象 × 1000 次 = 10 万对象/轮,JMH 5 轮预热 + 5 轮测量
口径原则所有框架关闭/开启等价特性(如都开反射、都关自动类型);不做框架未公开的极限调优,以“默认可用配置”为准

为什么强调“默认可用配置”:Fastjson2 开启 ASM 字节码生成后有额外性能,Jackson 开启 Afterburner/Blackbird 模块也有——都开的话差距会缩小。本文数据统一为各框架默认依赖引入后的行为,这也是 90% 项目真实的运行状态。

1.2 三类测试场景

// 场景一:序列化(Object → JSON String)
// 场景二:反序列化(JSON String → Object)
// 场景三:内存压力(Xmx 512m 下处理 10 万对象的 GC 行为)

二、维度一 & 二:序列化与反序列化吞吐

2.1 核心数据(嵌套订单对象,ops/s,越大越好)

框架序列化 ops/s相对值反序列化 ops/s相对值
Fastjson2~1,850,0001.00~1,320,0001.00
Jackson~1,680,0000.91~1,180,0000.89
Moshi(Java POJO)~920,0000.50~760,0000.58
Gson~640,0000.35~510,0000.39

云主机(4C8G Linux)复核对齐了相对排序,比例略有收敛(Gson 差距缩小到 0.45 左右)。

2.2 数据怎么读

  • Fastjson2 确实最快:得益于运行期 ASM 字节码生成(直接生成 getter/setter 调用代码,绕过反射缓存层),Jackson 紧随其后差距在 10% 以内——这个差距对绝大多数业务无感知
  • Gson 慢是设计取舍:全运行期反射 + 不做字节码增强,换来的是极小的 jar(~240KB)和最简单的 API;
  • Moshi 注意口径:对 Java POJO 用反射模式时中等偏上;Kotlin 类 + codegen(kotlin-codegen 模块)时编译期生成适配器,性能追平 Jackson 档位——表格里是 Java POJO 口径,Kotlin 项目请按后文结论取数。

一个重要提醒:10 万对象场景下,四个框架的绝对耗时都在百毫秒级以内。如果你的系统瓶颈是 JSON 序列化,大概率问题出在“序列化次数太多”或“对象图太大”,而不是框架本身——换库优化收益通常小于设计优化(减少序列化体积、流式处理、按需字段)。


三、维度三:内存占用

3.1 实测结果

框架jar 体积10 万对象反序列化峰值内存GC 行为
Gson~240KB~380MB平稳
Moshi~100KB(核心)+ codegen 产物~350MB平稳
Jackson~2MB(databind+core+annotations)~420MB平稳,Full GC 频率低
Fastjson2~1.6MB~390MB平稳

3.2 怎么读

  • 运行期内存差距远小于性能差距(都在 ±10% 内)——序列化器对象复用良好时,框架自身元数据开销不是大头,对象图本身才是内存主体
  • 真正拉开差距的是依赖体积:Android 端 240KB(Gson)vs 2MB+(Jackson 全家桶)在 APK 大小敏感场景是实打实的差异;
  • Jackson 元数据更占内存(BeanDeserializer 缓存粒度细),但换来的是功能表达力——天下没有白吃的午餐。

四、维度四:特性支持——拉开真实差距的地方

性能差不多时,特性能力才是日常开发的体感。四个维度逐项过:

4.1 日期/时间处理

框架java.time 支持格式自定义体感
Jackson✅ 原生(JavaTimeModule)@JsonFormat 精细到字段最强:LocalDateTime/Instant/Duration 全覆盖
Gson❌ 默认不支持(JDK8+ 时间类型输出怪异数组)需手写 TypeAdapter经典坑:LocalDate 序列化成 [2025,8,22]
Fastjson2✅ 支持@JSONField(format=...)良好
Moshi❌ 核心不带需自定义 Adapter(Kotlin 项目常用社区 adapter)中性
// Gson 处理 LocalDate 的标准姿势(每个项目都要写一遍的样板代码)
Gson gson = new GsonBuilder()
    .registerTypeAdapter(LocalDate.class,
        (JsonSerializer<LocalDate>) (src, t, c) ->
            new JsonPrimitive(src.format(DateTimeFormatter.ISO_LOCAL_DATE)))
    .create();

4.2 字段映射策略

能力JacksonGsonFastjson2Moshi
改名@JsonProperty@SerializedName@JSONField@Json(name=)
蛇形↔驼峰全局策略✅ PropertyNamingStrategies✅ FieldNamingPolicy社区 adapter
嵌套扁平化/展开@JsonUnwrapped 等部分
泛型保留TypeReference 成熟TypeToken 成熟TypeReferenceTypeToken
多态序列化@JsonTypeInfo 完整体系RuntimeTypeAdapter支持,边界多有限

4.3 忽略/空值策略

能力JacksonGsonFastjson2Moshi
字段级忽略@JsonIgnore / transient@Expose 反向标记 / transient@JSONField(serialize=false)@JsonIgnore 社区 adapter
null 处理(全局/字段级)@JsonInclude 五档精细默认忽略 null(不可关!需显式策略)WriteMapNullValue 可控默认带 null
只读/只写方向@JsonIgnoreProperties(readOnly) 读写分离

这里有个高频事故点:Gson 默认丢弃 null 字段——字段值为 null 时输出 JSON 里直接没有这个 key。后端对接方如果依赖“字段存在与否”的语义(如 PATCH 语义),Gson 的默认行为会安静地造成协议不一致。Jackson 默认输出 null(可用 @JsonInclude(NON_NULL) 优化),行为更显式。

4.4 高级特性(选型分水岭)

特性JacksonGsonFastjson2Moshi
流式 API(JsonParser/Generator)✅ 完整(大文件处理基础)✅ JsonReader/Writer
树模型JsonNode 强大JsonElementJSONObjectJsonReader 可遍历
JSON 视图/版本控制@JsonView(按场景裁剪字段)
合并/更新既有对象readerForUpdating
自定义序列化器生态海量模块(Joda、Kotlin、JDK8、Avro…)TypeAdapter 生态分散注解体系Adapter 生态清晰

结论:特性维度 Jackson 断层领先。@JsonView(一套实体多端裁剪)、readerForUpdating(PATCH 语义合并)、多态体系,这些“不常用但一用就是刚需”的能力只有 Jackson 全都拿得出手。


五、维度五:安全性——绕不开的历史包袱

5.1 Fastjson 的漏洞史

选型讨论绕不开这段历史,客观列出关键节点:

年份漏洞类型影响
2017反序列化 RCE(autoType 首爆)远程代码执行大量企业中招,官方开 autoType 黑名单模式
2019~2020autoType 黑名单绕过连环爆(CVE-2019-16865 等)RCE“黑名单封不完”暴露治理模式缺陷
2022Fastjson 1.x 又爆 autoType 绕过RCE直接催生 Fastjson2 的架构重构
2022+Fastjson2 发布,默认禁用 autoType、重构解析器安全模型大幅收敛

5.2 客观看待:Fastjson2 现状与使用纪律

Fastjson2 不是 Fastjson 1.x——autoType 默认关闭、解析器重写、安全团队持续跟进,近两年未再出现同等量级 RCE。但选型时的“安全包袱”评估是合理的,因为:

  1. 历史欠账:存量系统里 Fastjson 1.x 仍有大量未升级实例(专项行动数据屡见不鲜),同一个团队同时维护 1.x/2.x 的心智成本高;
  2. autoType 需求仍在:部分老代码依赖 @type 多态能力,开启就重新暴露风险面;
  3. 审计成本:安全团队对“引入 Fastjson 系”的评估成本高于引入 Jackson——这是真实的组织成本。

如果确实要用 Fastjson2,四条纪律:autoType 保持关闭(确需多态用 Jackson 的 @JsonTypeInfo 或显式白名单);只升级不降级(盯 release note);统一版本收口(禁止各服务自选 1.x/2.x);对外解析的 JSON 一律过长度/深度/字段白名单校验。

5.3 其他三家的安全面

框架安全画像
Jackson默认开启多态类型(enableDefaultTyping 需显式)时曾有 CVE 历史——同样要纪律:不用 default typing、升级到 2.16+(新 polymorphic 处理已收紧)
Gson反序列化面窄、攻击面小;老版本曾曝 DoS 类问题(2.8.9 修复),保持升级即可
Moshi无重大 CVE 记录,攻击面小(Kotlin 生态默认不信运行期类型)

公平地说:JSON 库的安全风险主要来自“多态/自动类型 + 不可信输入”这个组合。谁都没有豁免权,但 Fastjson 1.x 的历史让它的默认信任度确实低了一档。


六、维度六:社区活跃度与生态

维度JacksonGsonFastjson2Moshi
维护方FasterXML(Fabloo)Google阿里Square
GitHub Stars~9k+(生态远大于本体)~23k~25k(含 1.x)~10k
Release 频率稳定季度级年度级活跃月级活跃
框架集成Spring Boot 默认 / JAX-RS / Quarkus 全支持手动集成为主需替换 HttpMessageConverterAndroid/Kotlin 生态
文档与问答StackOverflow 沉淀最深丰富中文社区强Kotlin 社区强
商业与规范背书JCP 相关规范参与者

生态维度的实质差异:Jackson 不只是一个库,是 Java JSON 事实标准——Spring 全家桶的消息转换、各种云 SDK、日志字段处理,默认都跑在 Jackson 上。选 Jackson = 享受整个默认生态;选其他框架 = 主动接管并维护“框架默认 Jackson”与“你选的库”并存的复杂度(双库共存还可能引发类冲突与行为不一致)。


七、选型结论:按场景对号入座

7.1 决策表

场景推荐理由
服务端 / Spring Boot 微服务(默认答案)JacksonSpring 原生集成、特性断层领先、生态即标准;性能与 Fastjson2 差距 <10% 无感知
超高吞吐 JSON 网关/代理(已用 Jackson 仍不够)Fastjson2(守纪律)ASM 加持的极限吞吐;配合 5.2 四条纪律
Android / APK 体积敏感 + 简单数据Gson 或 Moshi240KB vs 2MB 的依赖差异;特性需求简单时二者都够
Kotlin 项目(服务端或移动端)Moshi + codegen空安全/默认值/data class 天然契合,编译期适配器性能追平第一梯队
遗留 Fastjson 1.x 系统计划性迁 Jackson 或 Fastjson21.x 停止功能维护,安全风险敞口该关了

7.2 一张图总结

性能 ↑
                     │
          Fastjson2 ●│
                     │   ● Jackson
        (守纪律使用) │  (全能王:特性+生态+第一梯队性能)
                     │
   ──────────────────┼──────────────────→ 特性/生态
                     │
              Gson ● │        ● Moshi(codegen)
          (轻量简单)│      (Kotlin 最优解)
                     │

八、常见问题

8.1 我们项目已经用了 Fastjson 1.x,怎么迁?

两条路径按团队情况选:迁 Jackson(推荐,一劳永逸):全局替换 API + 注解映射表(@JSONField→@JsonProperty、@JSONPOJOBuilder 对应项)+ 回归评测集;迁 Fastjson2(改动最小):包名从 com.alibaba.fastjson 改 fastjson2(官方提供兼容包 fastjson1-compatible 过渡),注意 autoType 行为差异点逐个确认。无论哪条路,先建 100 条序列化/反序列化对拍用例(老库输出 vs 新库输出逐字段 diff),再动生产。

8.2 Jackson 性能比 Fastjson2 差 10%,要紧吗?

算笔账:一个服务序列化占 CPU 的 5%(已属重度),换库全量提速 10% = 整体 CPU 省 0.5%——不及一次无效 GC 调优的收益。性能维度真正值得动手的信号:火焰图上 Jackson 相关占比 >15%、或单条消息 MB 级(此时该考虑流式处理/字段裁剪,而不是换库)。

8.3 Gson 默认丢 null 字段,怎么补救?

new GsonBuilder().serializeNulls().create() 全局开启;但更好的姿势是团队规约禁止裸 new Gson()(统一走 GsonFactory),在工厂里固化 serializeNulls + 版本字段策略 + 自定义 TypeAdapter 集合。Gson 的问题从来不是“不能配”,而是“默认值太隐式,不读文档不知道”。

8.4 同一项目里 Jackson 和 Gson 共存安全吗?

能跑,但要立三条规矩:职责切分(Spring 层用 Jackson、特定 SDK 对接用 Gson)、依赖收敛(BOM 锁版本)、禁止互相喂对方输出的字符串(行为差异:null、日期、数字精度)。共存的本质成本是“两个语义世界的对账”,能用一个就别用两个。

8.5 Kotlin 项目选 Moshi 还是继续用 Jackson?

服务端 Kotlin + Spring:继续 Jackson(配 jackson-module-kotlin),因为消息转换、监控、序列化生态都是 Jackson 的,Moshi 换进去收益只有 Kotlin 数据类映射一点;Kotlin-first 的库/SDK/多平台项目:Moshi + codegen 是更地道的答案(空安全、默认值、sealed class 的 polymorphic 支持更符合 Kotlin 心智)。

8.6 横评数据会过时,那方法论呢?

数据会过时(本文版本对应 2025 年上半年),但这套六维评测框架不会:吞吐/反序列化/内存/特性/安全/生态,六维打分按你的场景加权。建议把 JMH 基准和评测对象留在团队仓库里,新版本发布时跑一遍,选型结论持续保鲜——比看任何博客(包括这篇)都可靠


九、总结

六维横评总表

┌──────────────┬──────────┬────────┬───────────┬────────┐
│ 维度          │ Jackson  │ Gson   │ Fastjson2 │ Moshi  │
├──────────────┼──────────┼────────┼───────────┼────────┤
│ 序列化吞吐    │ 0.91 ★★  │ 0.35   │ 1.00 ★★★  │ 0.50 ★ │
│ 反序列化      │ 0.89 ★★  │ 0.39   │ 1.00 ★★★  │ 0.58 ★ │
│ 内存/体积     │ ★★       │ ★★★ 最小│ ★★        │ ★★★    │
│ 特性支持      │ ★★★ 断层 │ ★★     │ ★★        │ ★★     │
│ 安全性        │ ★★       │ ★★     │ ★(+纪律) │ ★★     │
│ 社区/生态     │ ★★★ 标准 │ ★★     │ ★★        │ ★★     │
└──────────────┴──────────┴────────┴───────────┴────────┘
结论:Jackson 全能王 / Fastjson2 性能王(守纪律)/
      Gson 轻量简单场景 / Moshi Kotlin 最佳

一句话

JSON 库选型的正确姿势是六维打分而不是只看跑分:性能上 Fastjson2 最快但领先不足 10%,业务无感知;Jackson 赢在特性断层(日期/多态/视图/模块生态)和“Spring 默认”这个生态事实标准;Gson 的 240KB 和零学习成本适合轻场景,但默认丢 null 的隐式行为要设防;Moshi 是 Kotlin 项目的地道答案。安全维度没有豁免者——多态+不可信输入是所有库的雷区,纪律比选型更重要。

给团队的建议

建议
服务端默认Jackson(Spring 默认,别引入第二套 JSON 库)
严禁裸用new Gson() / new ObjectMapper() 裸用——统一工厂收口配置
Fastjson 1.x列入清退计划,迁移前先建对拍用例集
Android/KotlinMoshi + codegen;体积敏感且数据简单用 Gson
性能优化先查序列化占比(火焰图),再谈换库
保鲜JMH 基准留在仓库,大版本发布重跑横评

互动话题:你们团队用的哪个 JSON 库?有没有被 Fastjson autoType 或 Gson 丢 null 坑过的经历?评论区聊聊你的选型故事。


参考资料


标题:JSON 序列化框架性能横评:Jackson vs Gson vs Fastjson2 vs Moshi——不只是快慢
作者:jiangyi
地址:http://www.jiangyi.space/articles/2026/09/10/1788595691805.html
公众号:服务端技术精选
    评论
    0 评论
avatar

取消