Spring Boot 4 升级为什么卡在 Jackson 3?包名、配置与兼容迁移指南

技术范围:Java 17+、Spring Boot 4.x、Spring Framework 7、Jackson 2/3、Spring MVC

一、先说结论:Boot 4 升级不只是改版本号

不少团队把 Spring Boot 3.x 的版本号改成 4.x 后,遇到这样的编译或运行问题:

  • com.fasterxml.jackson.databind.ObjectMapper 相关代码无法直接适配新的自动配置;
  • @JsonComponent、定制序列化器、ObjectMapper Bean 配置需要调整;
  • 项目同时存在 Jackson 2 和 Jackson 3,导致序列化结果、消息转换器或第三方组件行为不一致;
  • 升级后日期、数字、空值、字段命名的 JSON 输出发生变化。

核心原因之一是 Spring Boot 4 默认转向 Jackson 3,而 Jackson 3 不只是“原来的库升级一个大版本”:包名、部分 API、默认行为和 Spring Boot 集成方式都发生了变化。

如果只记住一个升级策略,我建议:先盘点 JSON 边界和依赖,再迁移 Jackson;先通过契约测试,再切换生产流量。

官方资料:2025-11-20 Spring Boot 4.0.0 发布公告;Spring Boot 4 迁移指南。

二、Jackson 2 与 Jackson 3 最直观的区别

Spring 官方在 2025-10-07 专门解释过 Jackson 3 集成策略:Boot 4 和 Framework 7 默认使用 Jackson 3,同时暂时保留 Jackson 2 的迁移通道。

维度 Jackson 2 Jackson 3
Maven 坐标(典型) com.fasterxml.jackson.core:jackson-databind tools.jackson.core:jackson-databind
核心类包名 com.fasterxml.jackson.databind.ObjectMapper tools.jackson.databind.json.JsonMapper
Spring Boot 4 默认 兼容性支持(已弃用) 首选与默认
注解包 com.fasterxml.jackson.annotation 多数常用注解仍保留这个包名
迁移重点 旧 API 与配置 新 API、默认值和依赖链

不要把所有 com.fasterxml.jackson.* 一键替换为 tools.jackson.*。例如 jackson-annotations 保留原来的 groupId 与包名,这是官方明确的兼容例外。

也不要认为“依赖树中出现 Jackson 2 就一定冲突”:官方允许两代库并存,真正要检查的是哪个 Mapper 和哪个 HTTP MessageConverter 在处理请求。

三、第一步:用依赖树确认实际版本

Maven 项目执行:

mvn dependency:tree -Dincludes=com.fasterxml.jackson.core:*,tools.jackson.core:*

如果 Maven 插件或 Shell 对参数通配符处理不一致,可先使用:

mvn dependency:tree | grep -Ei 'jackson|spring-boot'

Windows PowerShell 可以使用:

mvn dependency:tree | Select-String 'jackson|spring-boot'

重点核对:

  1. Spring Boot BOM 实际管理的版本。
  2. Web、Security、Redis、OpenFeign、HTTP 客户端等组件是否引入旧 Jackson。
  3. 是否手工声明了旧版 ObjectMapper Bean。
  4. JSON 序列化工具类是否硬编码 Jackson 2 类型。

切勿为消除依赖树中的 Jackson 2 而盲目排除所有传递依赖,某些第三方组件仍依赖旧版解析器。要结合其兼容说明逐个处理。

四、第二步:改造 JsonMapper,而不是只改 import

Spring Boot 4 的 spring-boot-starter-json 使用 Jackson 3;当 Jackson 3 在类路径上时,Boot 会自动配置 JsonMapper Bean。

在 Spring Boot 3 时代,很多项目这样使用:

import com.fasterxml.jackson.databind.ObjectMapper;

@Service
public class JsonService {
    private final ObjectMapper mapper;
    public JsonService(ObjectMapper mapper) {
        this.mapper = mapper;
    }
}

迁移到 Jackson 3 时,更推荐围绕 JsonMapper 建立新代码:

import tools.jackson.databind.json.JsonMapper;

@Service
public class JsonService {
    private final JsonMapper mapper;

    public JsonService(JsonMapper mapper) {
        this.mapper = mapper;
    }

    public String toJson(Object value) {
        return mapper.writeValueAsString(value);
    }
}

以上代码是核心依赖注入片段,假设项目使用 Spring Boot 4 的默认 Jackson 3 自动配置,@Service 等 Spring 注解需正常导入。

为什么优先注入容器的 Mapper?因为它承载了全局日期格式、模块注册、属性配置等统一行为。到处 new JsonMapper() 可能造成控制器返回 JSON 与后台任务输出 JSON 不一致。

五、第三步:检查注解与配置迁移

1. @JsonComponent 更名

Spring Boot 4 中,原来的 @JsonComponent 更名为 @JacksonComponent,@JsonMixin 对应 @JacksonMixin。如果你有自定义序列化器和反序列化器,需要检查相关类型和注册方式,而不是只修改注解名称。

2. JSON 配置层级发生变化

例如原来位于 spring.jackson.read.*、spring.jackson.write.* 的 JSON 专属配置迁移到:

spring:
  jackson:
    json:
      read:
        # 在这里配置目标版本支持的具体读取选项
      write:
        # 在这里配置目标版本支持的具体写入选项

上面的 YAML 仅展示属性层级,不是可以直接复制的完整配置。具体枚举属性名和取值必须对照目标 Boot 4.x 的配置元数据核实。

3. 默认行为改变怎么办?

如果现有客户端依赖 Jackson 2 的历史序列化行为,可以临时启用:

spring:
  jackson:
    use-jackson2-defaults: true

该选项是让 Jackson 3 的默认行为尽可能接近 Spring Boot 3 中的 Jackson 2,并不保证所有 JSON 完全相同。尤其是日期格式、自定义序列化器、多态类型、空值、浮点数等,仍应通过真实请求与历史快照对比。

官方迁移指南:https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-4.0-Migration-Guide

六、暂时迁不了 Jackson 3,能否先升级 Spring Boot 4?

可以作为过渡方案,但不能当作长期策略。

Spring Boot 4 仍提供已弃用的 spring-boot-jackson2 模块,供无法立刻迁移的应用使用。官方示例依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-jackson2</artifactId>
</dependency>

但如果默认的 Jackson 3 自动配置仍在类路径上,不能指望只加这个依赖就能把整个应用“切回 Jackson 2”。需要根据具体 Starter 依赖树排除不需要的 Jackson 3 自动配置模块,并核实 MVC 消息转换器的实际选择。

Jackson 2 兼容属性使用 spring.jackson2 前缀。官方已明确这条兼容路径将来会移除,所以应同时建立迁移计划,而不是永久停留在双版本状态。

迁移路线建议

原系统:Spring Boot 3 + Jackson 2
          │
          ├── 路线 A:直接升级 Boot 4 + Jackson 3
          │             ↓
          │        契约测试与回归
          │
          └── 路线 B:Boot 4 + 临时 Jackson 2
                        ↓
                 单独迁移 Jackson 3
                        ↓
                 删除兼容依赖

对业务量大、第三方组件多的系统,路线 B 有时更容易隔离变更范围;但它也增加了过渡期维护成本。

七、不要只测“应用能启动”,要测 JSON 契约

升级最危险的结果不是启动失败,而是服务正常启动,但客户端看到的 JSON 变了。

建议至少覆盖下面的场景:

场景 测试重点
日期时间 时区、偏移量、精度、ISO 格式
金额与数字 BigDecimal、浮点精度、整数范围
null / 缺失字段 默认值、校验、字段是否输出
枚举 字符串、数字、大小写
多态对象 类型标识、白名单、反序列化安全
Redis 缓存 旧序列化数据是否还能读
消息队列 旧生产者和新消费者是否兼容
对外 API 手机端、第三方客户端是否依赖历史格式

一个简洁的 MockMvc 测试思路:

@SpringBootTest
@AutoConfigureMockMvc
class JsonContractTests {

    @Autowired
    MockMvc mvc;

    @Test
    void productJsonContract() throws Exception {
        mvc.perform(get("/api/products/1"))
           .andExpect(status().isOk())
           .andExpect(jsonPath("$.id").value(1))
           .andExpect(jsonPath("$.price").exists());
    }
}

上面是测试结构示例,依赖实际项目的控制器、数据准备与对应 Boot 4 测试模块配置;不能将其视为已在某个具体工程运行通过的完整测试。更推荐把升级前真实响应保存为脱敏的 JSON 契约样本,升级后对比关键字段和值类型。

八、生产升级前的六项检查

  1. 确认运行基线:Spring Boot 4 支持 Java 17,别把“支持 Java 25”误解为“最低要求 Java 25”。
  2. 看迁移指南:Boot 4 不止 Jackson 变化,还有模块拆分、Spring Framework 7、JSpecify 和 API 版本化等。
  3. 检查第三方 Starter:特别是 Spring Cloud、Security、Redis、数据库与监控依赖的兼容矩阵。
  4. 验证 Mapper 来源:确认控制器、工具类、消息消费者是否使用预期的 Jackson 版本。
  5. 灰度与回滚:保存升级前 JSON 契约和配置;必要时先灰度流量。
  6. 监控异常:重点观察 400、415、500、反序列化异常、客户端兼容问题。

九、常见问题

Spring Boot 4 必须使用 Java 25 吗?

不需要。Spring Boot 4.0 官方发布说明明确保留 Java 17 兼容性,并增加 Java 25 一等支持。

Jackson 3 能直接读取所有 Jackson 2 生成的 JSON 吗?

不能一概而论。常规 JSON 数据可能兼容,但类型信息、自定义序列化器、日期格式和历史二进制/缓存数据需要逐项验证。

能不能把 Jackson 2 和 Jackson 3 同时放在一个应用里?

官方支持迁移期并存,但要避免不同 Mapper、HTTP 转换器和缓存序列化器无意间混用。双版本并存是过渡手段,不是默认推荐的最终状态。

Spring Boot 4 是 2026 年 11 月刚发布的吗?

不是。Spring Boot 4.0.0 于 2025 年 11 月 20 日 发布。本文聚焦的是目前仍具有工程价值的 Jackson 3 迁移问题,不把旧发布当成当天新闻。

总结

Spring Boot 4 升级中的 Jackson 3 问题,本质上是框架默认行为与应用长期积累的 JSON 契约发生交汇。正确顺序不是“全局替换包名 → 编译成功 → 直接上线”,而是:

依赖盘点 → Mapper 与配置迁移 → JSON 契约回归 → 灰度发布 → 清理过渡依赖。

如果你正在维护长期运行的 Java 系统,这些工作比追逐最新版本号更重要。

参考资料(官方)

posted @ 2026-11-05 08:40  杨凯凡  阅读(20)  评论(0)    收藏  举报