Spring 中引入 Jackson 3 支持

工程 | Sébastien Deleuze | 2025年10月7日 | ...

这是“通往GA之路”系列中的一篇新博文,就在Jackson 3.0.0 GA发布几天后,此篇博文分享了更多关于Jackson 3新支持的细节,该支持即将引入到Spring Boot 4及相关的Spring项目组合中。

Jackson是目前JVM上最常用的JSON库,Spring中引入Jackson 3的支持是我们提供额外增强的机会,这是我在10多年前宣布的广受欢迎的Spring中Jackson集成改进的后续!

Spring和Jackson团队之间的紧密合作

当 Spring 团队致力于利用流行开源库的新版本时,虽然可能不明显,但部分工作有时是与维护者合作进行改进,这将有益于更广泛的社区。

Jackson 3 就是一个很好的例子,我要感谢 Tatu Saloranta(Jackson 项目负责人)在发布候选阶段愿意听取我们的反馈——这使得以下改进成为可能:

Spring Boot 4.0 中 Jackson 支持的现状

一般原则是,自 Spring Boot 4.0 和 Spring Framework 7.0 起,Spring 产品组合将:

  • 引入 Jackson 3 支持
  • 弃用 Jackson 2 支持,并最终移除
  • 将默认 Jackson 版本(类路径检测、依赖项)切换到 Jackson 3

主要例外是 Spring AI,它打算在 2026 年上半年发布的 2.0 版本中引入 Jackson 3 支持。

更具体地说,Spring Boot 4.0 将:

  • 为 Jackson 2 和 3 提供依赖管理
  • 执行 Jackson 3 的自动配置
  • 弃用 Jackson 2 的自动配置,并最终移除
  • 在其 spring-boot-starter-jsonspring-boot-starter-jackson 启动器依赖项中使用 Jackson 3

升级到 Spring Boot 4.0 时,建议的顺序是:

  1. 迁移到 Jackson 3
  2. 迁移到 Jackson 3 并设置 spring.jackson.use-jackson2-defaults
  3. 暂时使用 Jackson 2,以方便迁移到 Spring Boot 4.0,作为向 Jackson 3 过渡的垫脚石

仍依赖 Jackson 2 的传递依赖项仍受支持,并将受益于 Jackson 2 依赖管理。

迁移到 Jackson 3

本节重点介绍典型 Spring Boot 应用程序最重要的迁移步骤,有关其他方面的更多详细信息,请参阅 Jackson 3 迁移指南。相关的 Open Rewrite 配方 可以帮助自动化其中一些更改,而 Spring Application Advisor 将为您的 Spring Boot 应用程序的增量迁移提供最全面的选项。

更新包

升级时遇到的第一个破坏性更改可能是 Jackson 包(和依赖项 groupID)从 com.fasterxml.jackson 更改为 tools.jackson除了 jackson-annotations,它出于向后兼容性原因保持不变

适应新的默认设置

Jackson 3 更改了一些默认设置,与 Jackson 2 相比,因此您应该相应地调整测试(如果可以,建议这样做),或者自定义 Jackson 3 配置以恢复一些以前的默认设置。

最可能破坏测试的更改如下:

  • 如果您在测试中将 Jackson 序列化与原始字符串进行比较,则很可能会受到 MapperFeature.SORT_PROPERTIES_ALPHABETICALLY 现在设置为 true 的影响。
  • SerializationFeature.WRITE_DATES_AS_TIMESTAMPS 现在称为 DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS 已更改为 false,以将日期序列化为 ISO-8601 字符串。

如果您至少最初希望尽可能使用与 Jackson 2 相似的默认设置,则可以使用 spring.jackson.use-jackson2-defaults 属性。当设置为 true 时,自动配置的 JsonMapper 将具有与 Spring Boot 3 中 Jackson 2 默认设置尽可能一致的默认设置。

Jackson 模块

一些以前的 Jackson 2 模块现在已内置于 Jackson 3 中,例如 parameter-names 或 datatype-jsr310。以前通过 Jackson2ObjectMapperBuilder 启用的其他模块现在通过 JDK 服务加载器设施自动发现,用于 Spring Framework 提供的转换器和编解码器。

当然,也可以通过 JsonMapper.Builder 配置自定义模块。

从 ObjectMapper 到 JsonMapper

Jackson 3 引入了许多更改和增强功能,但从 Spring 的角度来看,最重要的一项是从 Jackson 2 中可变的 ObjectMapper 切换到 Jackson 3 中不可变的 JsonMapper

JsonMapper 扩展了 ObjectMapper,专门用于 JSON 格式,遵循与其他格式(XmlMapperYAMLMapperSmileMapper 等)类似的模式,并且 Spring 支持已更新为使用此特定于格式的变体,遵循 Jackson 3 最佳实践。

此外,由于 Jackson 和 Spring 的默认设置大部分一致,并且引入了第一类 JsonMapper.BuilderSpring Framework 不再提供 Jackson2ObjectMapperBuilder 的等效项,您应该只使用 Jackson 构建器

例如,对于 Spring Boot 3 及其 Jackson 2 支持,spring.jackson.serialization.indent-output=true 的编程等效项是

@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() {
    return builder -> builder.indentOutput(true);
}

对于 Spring Boot 4 及其 Jackson 3 支持,它是

@Bean
JsonMapperBuilderCustomizer jacksonCustomizer() {
    return builder -> builder.enable(SerializationFeature.INDENT_OUTPUT);
}

再见 MappingJacksonValue

现在已弃用的 MappingJackson2HttpMessageConverter 扩展了 GenericHttpMessageConverter,后者无法正确传递额外的序列化信息,例如序列化视图或 FilterProvider,因此需要 MappingJacksonValue 包装器。

例如,假设我们使用 @JsonView(Summary.class) 注解 User 记录,以标识要序列化或反序列化的组件子集

public record User(
    @JsonView(Summary.class) String firstname,
    @JsonView(Summary.class) String lastname,
    LocalDate birthdate,
    @JsonView(Summary.class) String email,
    String address,
    int postalCode,
    String city,
    String country) {
}

使用 Spring Framework 6 及以前版本,在客户端您必须使用 MappingJacksonValue 包装器来指定应使用 Summary JSON 视图。

var user = new User("Marcel", "Martin", LocalDate.of(1971, 7, 12),
    "[email protected]", "1234 rue Gambetta", 69002, "Lyon", "France");
var jacksonValue = new MappingJacksonValue(user);
jacksonValue.setSerializationView(Summary.class);
var response = this.restTemplate.postForObject("https://:8080/create", jacksonValue, String.class);

这允许仅序列化用 @JsonView(Summary.class) 注解的记录组件

{
  "firstname" : "Marcel",
  "lastname" : "Martin",
  "email" : "[email protected]"
}

从 Spring Framework 7 开始,您可以利用基于 Jackson 3 的新 JacksonJsonHttpMessageConverter 实现了 SmartHttpMessageConverter,它支持序列化提示,因此您可以这样编写

var user = new User("Marcel", "Martin", LocalDate.of(1971, 7, 12),
    "[email protected]", "1234 rue Gambetta", 69002, "Lyon", "France");
var response = this.restClient.post().uri("https://:8080/create")
    .hint(JsonView.class.getName(), Summary.class).body(user)
    .retrieve().body(String.class);

不再有可变包装器,只有可选的提示。

暂时继续使用 Jackson 2 支持

建议迁移到 Spring Boot 4 的应用程序迁移到 Jackson 3,但如果需要,可以继续使用 Jackson 2,甚至同时使用 Jackson 2 和 3。请注意,这可能需要额外的依赖项和配置改进。

如果您想暂时继续使用 Jackson 2 支持而不是 Jackson 3,您可以例如:

  • 排除 spring-boot-jackson 的直接或传递依赖项(例如,来自 spring-boot-starter-jacksonspring-boot-starter-json),并改用 spring-boot-jackson2
  • 对于配置属性,使用 spring.jackson2 而不是 spring.jackson

Jackson 2 自动配置以弃用形式保留了一段时间,仅用于帮助逐步迁移到 Jackson 3。

Spring Security Jackson 3 支持

Spring Security 7.0 引入了Jackson 3 支持,并弃用了 Jackson 2 支持。

它还通过利用 PolymorphicTypeValidator 使 Jackson 支持更安全,其中默认只允许 Spring Security 类型,并为应用程序提供了添加自己类型的能力,例如

ClassLoader loader = getClass().getClassLoader();
BasicPolymorphicTypeValidator.Builder typeValidatorBuilder = BasicPolymorphicTypeValidator.builder()
    .allowIfSubType(CustomGrantedAuthority.class);
JsonMapper mapper = JsonMapper.builder()
    .addModules(SecurityJacksonModules.getModules(loader, typeValidatorBuilder))
    .build();

Jackson 3 支持使用与现在已弃用的 Jackson 2 兼容的格式,因此使用 Jackson 2 序列化的类实例应该可以使用 Jackson 3 支持进行反序列化。

Spring Data Jackson 3 支持

Spring Data 4.0 及其核心模块完全支持 Jackson 3。建议迁移到 Spring Data 4 的应用程序迁移到 Jackson 3,但如果需要,可以继续使用 Jackson 2,甚至同时使用 Jackson 2 和 3。请注意,Jackson 3 附带了一组不同的默认设置,这可能需要迁移您的持久数据或更新 Jackson 3 默认设置以匹配 Jackson 2 设置。

由于 Spring Data 包含大量项目,让我们单独探讨每个模块:

Spring Data Commons

Spring Data Commons 添加了对 Jackson 3 的支持,如果类路径中只有 Jackson 2,则会回退到 Jackson 2。这主要适用于通过 ProjectingJacksonHttpMessageConverterSpringDataWebConfiguration 的 Web 支持。

JacksonResourceReaderJacksonRepositoryPopulatorFactoryBeanJackson2ResourceReaderJackson2RepositoryPopulatorFactoryBean 的基于 Jackson 3 的变体。

如果您使用 Jackson 2 以及 Spring Data 的 XML 命名空间支持 (<repository:jackson2-populator …>),并且您想迁移到 Jackson 3,那么您将必须在 Java 配置中定义一个 JacksonRepositoryPopulatorFactoryBean bean。

如果您碰巧使用 SpringDataJacksonModules,那么您需要考虑迁移到 SpringDataJackson3Modules,以实现基于 Jackson 3 的模块安排。

Spring Data Redis

Spring Data Redis 4.0 附带了用于 Jackson 3 的 JacksonHashMapperJacksonJsonRedisSerializerGenericJacksonJsonRedisSerializer 实现。在使用 JacksonObjectReaderJacksonObjectWriter 时,请确保使用 Jackson2ObjectReaderJackson2ObjectWriter 对您的实现进行改造,因为类命名已对齐以实现一致的方案。

Spring Data REST

Spring Data REST 本质上是一个围绕 Jackson 的大型包装器,不支持使用 Jackson 2 的操作模式。如果您想使用新的 Spring Data REST 版本,则您的应用程序必须迁移到 Jackson 3。Spring HATEOAS 也是如此,因为这两个框架都大量使用 Jackson。

Spring Data Couchbase、Elasticsearch、驱动程序

更大的生态系统正在缓慢追赶 Jackson 3。Couchbase、Elasticsearch 和一些驱动程序内部使用 Jackson 2,并将继续这样做。在大多数情况下,这些组件中的 Jackson 用法与您的实体无关,因为它是它们作为 JSON 解析器和写入器的机制。

结论

Jackson 3 在安全性、API、默认配置和功能方面带来了巨大的好处,但它也带来了需要一些迁移工作的破坏性更改,Spring 团队完全意识到这一点,并投入了大量精力提供最佳的安排和相关指导,并为以前的版本提供行业领先的扩展支持,以便您有时间进行升级。

一如既往,我们期待您的反馈,并将尽最大努力改进我们的指导、文档并回答您的相关问题。

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有