bigywater.tech
Spring · 186

fastjson2 与 Jackson:耗时只有 0.42 和 0.20,但 null、日期、未知字段、有参构造器的默认行为差别不小

fastjson2 和 Jackson 到底差多少?null 字段、日期、未知字段、枚举写错、末尾多个逗号各怎么处理?Jackson 3 有什么新坑?这篇用同一个对象在本机逐项试。

0.42 和 0.20
fastjson2 的耗时相对 Jackson 3.1:序列化 0.42,反序列化 0.20
Jackson 3 的新坑
带 -parameters 编译、类里有 public 有参构造器时,Jackson 3.1 选用它,{"x":"a","y":2} 反序列化抛 Cannot map null into type int
四种时间写法
同一个时间在 fastjson2、Jackson 2.21、Jackson 3.1 里有空格串、毫秒数、数组、ISO 串四种写法

序列化输出

实测 · 本机执行输出
  fastjson2:{"amount":12.50,"attrs":{"channel":"web","zone":"cn"},"id":1001,"items":[{"price":1.5,"qty":1,"sku":"sku-1"},{"price":3.0,"qty":2,"sku":"sku-2"},{"price":4.5,"qty":3,"sku":"sku-3"},{"price":6.0,"qty":4,"sku":"sku-4"},{"price":7.5,"qty":5,"sku":"sku-5"}],"name":"订单","paid":true,"status":"PAID","ts":1700000000000}
  Jackson 2.21(默认 ObjectMapper):{"id":1001,"name":"订单","amount":12.50,"status":"PAID","paid":true,"ts":1700000000000,"remark":null,"items":[{"sku":"sku-1","qty":1,"price":1.5},{"sku":"sku-2","qty":2,"price":3.0},{"sku":"sku-3","qty":3,"price":4.5},{"sku":"sku-4","qty":4,"price":6.0},{"sku":"sku-5","qty":5,"price":7.5}],"attrs":{"channel":"web","zone":"cn"}}
  Jackson 3.1(默认 JsonMapper):{"amount":12.50,"attrs":{"channel":"web","zone":"cn"},"id":1001,"items":[{"sku":"sku-1","qty":1,"price":1.5},{"sku":"sku-2","qty":2,"price":3.0},{"sku":"sku-3","qty":3,"price":4.5},{"sku":"sku-4","qty":4,"price":6.0},{"sku":"sku-5","qty":5,"price":7.5}],"name":"订单","paid":true,"remark":null,"status":"PAID","ts":1700000000000}

null 字段与键顺序的差别。

日期

实测 · 本机执行输出
  fastjson2:{"d":"2020-01-02 03:04:05","t":"2020-01-02 03:04:05"}
  Jackson 2.21 没有注册 java.time 模块:异常 InvalidDefinitionException:Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.da
  Jackson 2.21 注册了 JavaTimeModule:{"d":1577934245000,"t":[2020,1,2,3,4,5]}
  Jackson 3.1 默认:{"d":"2020-01-02T03:04:05.000Z","t":"2020-01-02T03:04:05"}

Date 与 LocalDateTime 的默认写法。

不规范输入

实测 · 本机执行输出
  public 有参构造器 Odd(String p, int q)(参数名与属性 x、y 不同,javac 带 -parameters),同时有无参构造器,输入 {"x":"a","y":2}:
    fastjson2:x=a,y=2
    Jackson 2.21:x=a,y=2
    Jackson 3.1:异常 MismatchedInputException:Cannot map `null` into type `int` (set `DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES` to 'false' to allo
  多出一个未知字段 extra:
    fastjson2:id=1,name=n,status=null,paid=false,ts=0,amount=null
    Jackson 2.21:异常 UnrecognizedPropertyException:Unrecognized field "extra" (class demo.Order), not marked as ignorable (9 known properties: "remark", "status"
    Jackson 3.1:id=1,name=n,status=null,paid=false,ts=0,amount=null
  键的大小写不同(NAME):
    fastjson2:id=1,name=null,status=null,paid=false,ts=0,amount=null
    Jackson 2.21:异常 UnrecognizedPropertyException:Unrecognized field "NAME" (class demo.Order), not marked as ignorable (9 known properties: "remark", "status",
    Jackson 3.1:id=1,name=null,status=null,paid=false,ts=0,amount=null
  枚举值不存在(UNKNOWN):
    fastjson2:id=1,name=null,status=null,paid=false,ts=0,amount=null
    Jackson 2.21:异常 InvalidFormatException:Cannot deserialize value of type `demo.Status` from String "UNKNOWN": not one of the values accepted for Enum
    Jackson 3.1:异常 InvalidFormatException:Cannot deserialize value of type `demo.Status` from String "UNKNOWN": not one of the values accepted for Enum
  数字写成字符串("id":"7"):
    fastjson2:id=7,name=null,status=null,paid=false,ts=0,amount=null
    Jackson 2.21:id=7,name=null,status=null,paid=false,ts=0,amount=null
    Jackson 3.1:id=7,name=null,status=null,paid=false,ts=0,amount=null
  Long 字段给空串:
    fastjson2:id=null,name=null,status=null,paid=false,ts=0,amount=null
    Jackson 2.21:id=null,name=null,status=null,paid=false,ts=0,amount=null
    Jackson 3.1:id=null,name=null,status=null,paid=false,ts=0,amount=null
  基本类型 boolean 给 null:
    fastjson2:id=null,name=null,status=null,paid=false,ts=0,amount=null
    Jackson 2.21:id=null,name=null,status=null,paid=false,ts=0,amount=null
    Jackson 3.1:异常 MismatchedInputException:Cannot map `null` into type `boolean` (set `DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES` to 'false' to
  基本类型 long 给 null:
    fastjson2:id=null,name=null,status=null,paid=false,ts=0,amount=null
    Jackson 2.21:id=null,name=null,status=null,paid=false,ts=0,amount=null
    Jackson 3.1:异常 MismatchedInputException:Cannot map `null` into type `long` (set `DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES` to 'false' to all
  BigDecimal 字段给数字 12.50:
    fastjson2:id=null,name=null,status=null,paid=false,ts=0,amount=12.50
    Jackson 2.21:id=null,name=null,status=null,paid=false,ts=0,amount=12.50
    Jackson 3.1:id=null,name=null,status=null,paid=false,ts=0,amount=12.50
  整个 JSON 末尾多了逗号:
    fastjson2:id=1,name=null,status=null,paid=false,ts=0,amount=null
    Jackson 2.21:异常 JsonParseException:Unexpected character ('}' (code 125)): was expecting double-quote to start field name at [Source: REDACTED (`S
    Jackson 3.1:异常 StreamReadException:Unexpected character ('}' (code 125)): was expecting double-quote to start property name at [Source: REDACTED

未知字段、大小写、枚举、null、末尾逗号,以及 Jackson 3.1 带 -parameters 时选用有参构造器。

不带 -parameters

实测 · 本机执行输出
  不带 -parameters,输入 {"x":"a","y":2}:
    fastjson2:x=a,y=2
    Jackson 2.21:x=a,y=2
    Jackson 3.1:x=a,y=2

三个库都成功。

耗时

实测 · 本机执行输出
  第 1 轮
    serFastjson2:312 ± 24 ns/op
    serJackson2:743 ± 19 ns/op
    serJackson3:742 ± 16 ns/op
    deFastjson2:389 ± 25 ns/op
    deJackson2:1495 ± 51 ns/op
    deJackson3:1940 ± 83 ns/op
  第 2 轮
    serFastjson2:319 ± 29 ns/op
    serJackson2:735 ± 23 ns/op
    serJackson3:745 ± 47 ns/op
    deFastjson2:391 ± 19 ns/op
    deJackson2:1569 ± 361 ns/op
    deJackson3:1919 ± 70 ns/op
  两轮平均(ns):serFastjson2 316;serJackson2 739;serJackson3 743;deFastjson2 390;deJackson2 1532;deJackson3 1930
  fastjson2 相对 Jackson 3 的耗时:序列化 0.42,反序列化 0.20(小于 1 表示 fastjson2 更快)

fastjson2 更快;Jackson 3.1 反序列化比 2.21 慢。

分步演示

FastJson2
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动(fastjson2 2.0.61,Jackson 2.21.5(com.fasterxml)与 Jackson 3.1.5(tools.jackson),jackson-datatype-jsr310;JVM 时区 UTC;JMH 1.37 avgt,3 次预热加 5 次测量各 1 秒,2 个 fork,整套基准跑两轮,Order 对象含 5 个 Item 和 2 个 attrs,反序列化用 Jackson 3 生成的那段 JSON)
    • 没有验证:多线程下的吞吐;大对象或大数组;fastjson2 的 JSONReader 特性开关(如 SupportSmartMatch 与大小写匹配的关系);fastjson 1.x;Jackson 的 Afterburner 或 Blackbird 模块;fastjson2 的安全问题与 autoType 默认设置;Spring MVC 里把 fastjson2 配成 HttpMessageConverter 的方式;Maven 与 Gradle 插件默认是否带 -parameters;Jackson 3.1 反序列化比 2.21 慢的原因;Jackson 3 选用有参构造器的规则细节
    京ICP备2026067502号-1京公网安备11010502063487号