Spring Boot 4 将默认 JSON 库从Jackson 2切换到了Jackson 3。
如果你是资深 Spring Boot 应用开发者,Jackson 一定不陌生,它是 Spring Boot 中Java 对象 ↔ JSON的事实标准。
Jackson 在 Spring Boot 4 中依赖结构大致是这样:
spring-boot-starter-jackson (4.x)├── tools.jackson.core:jackson-core:3.x ← Jackson 核心库└── com.fasterxml.jackson.annotation:jackson-annotations:2.x ← Jackson 注解
所以很多人在第一次查看项目依赖树时都会愣一下:
为什么项目里同时存在 Jackson 2 和 Jackson 3?
这是 Jackson 团队为了解决一个非常现实的问题:
整个 Java 生态不可能一夜之间全部迁移到 Jackson 3
他们的解决方案是:
•核心实现迁移到新包名•注解继续沿用旧包名
这意味着:
•@JsonView•@JsonFormat•@JsonIgnore•......
这些你用烂了的注解完全不用改, 可以让多个项目在 Jackson 2 / 3 之间渐进式迁移。
这是一次非常工程化、也非常现实的设计。
Spring Boot 4 默认升级到 Jackson 3 后,并不是换个版本号这么简单。 下面这 4 个变化,每一个都可能在升级时踩坑。
1. 包名变了:从com.fasterxml.jackson到tools.jackson
这是最直观、也是最容易编译报错的地方。
// Jackson 2import com.fasterxml.jackson.databind.ObjectMapper;// Jackson 3import tools.jackson.databind.ObjectMapper;
注意:
只有核心 API 换包名,注解依然在
com.fasterxml.jackson.annotation。
2.ObjectMapper退出舞台,JsonMapper成为主角
Jackson 2 的ObjectMapper是可变的:
ObjectMapper mapper = new ObjectMapper();mapper.enable(SerializationFeature.INDENT_OUTPUT);
这在多线程环境下其实并不安全。
Jackson 3 强制你使用Builder + Immutable(不可变)模式:
JsonMapper mapper = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES).build();
一旦build():
•配置被锁死•可以安全共享•天然线程安全
这是 Jackson 3 非常重要的一次设计升级。
Jackson 3 直接创建的
ObjectMapper只能得到默认配置,如果需要自定义配置,必须使用JsonMapper.builder()来创建不可变、线程安全的实例。
3. 日期序列化的默认值变了(非常容易踩坑)
版本 | 默认序列化 |
Jackson 2 | 时间戳 |
Jackson 3 | ISO-8601 字符串 |
// Jackson 2{"nowDate": 1767588151648}// Jackson 3{"nowDate": "2026-01-05T02:02:31.648Z"}
这对前端更友好,但会导致:
•依赖时间戳断言的老测试用例失败•与时间格式强绑定的接口约定、Mock 数据需要同步调整
临时兼容方案:
spring:jackson:use-jackson2-defaults: true
该配置会让 Jackson 3 尽量保持 Jackson 2 的默认行为,适合在迁移初期使用。
4.Checked Exception终于被干掉了
这是很多 Java 开发者拍手叫好的改动。
Jackson 2:
try {objectMapper.readValue(json, MyClass.class);} catch (IOException e) {...}
Jackson 3:
jsonMapper.readValue(json, MyClass.class);所有异常都继承自JacksonException(RuntimeException)。
最直接的好处是:
// Jackson 2:lambda 直接崩list.stream().map(o -> objectMapper.writeValueAsString(o)).toList();// Jackson 3:完全没问题list.stream().map(o -> jsonMapper.writeValueAsString(o)).toList();
这是真正为现代 Java 写法服务的设计。