PAYATHON 2026

Spring Boot 4 如何在保留自动配置的基础上定制 ObjectMapper?

数据阿明

在 Spring Boot 4 默认使用的 Jackson 3 环境中,可以声明一个 JsonMapperBuilderCustomizer Bean,在 Spring Boot 创建自动配置的 JsonMapper 时应用自定义设置。这样既能保留配置文件中的其他 Jackson 设置,也无需自行声明 ObjectMapper Bean。Spring Boot 定制说明

为什么原来的写法需要调整

tools.jackson.databind.ObjectMapper 属于 Jackson 3,而原代码中的 Jackson2ObjectMapperBuilder 面向 Jackson 2,不能只修改 ObjectMapper 的 import 后继续沿用。

Jackson 3 的 mapper 配置采用不可变设计,需要在 builder 阶段完成设置。因此,原来的 setTimeZone(...) 应改为 builder 上的 defaultTimeZone(...)。Jackson 3 迁移指南

使用 customizer 追加配置

移除原来的 objectMapper(...) Bean,添加以下配置类,并确保它位于 Spring 的组件扫描范围内:

import java.util.TimeZone;

import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import tools.jackson.databind.MapperFeature;

@Configuration(proxyBeanMethods = false)
public class JacksonConfiguration {

    @Bean
    @Order(1)
    public JsonMapperBuilderCustomizer applicationJsonMapperCustomizer() {
        return builder -> builder
                .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
                .defaultTimeZone(TimeZone.getDefault());
    }
}

Spring Boot 使用定制后的 builder 创建 JsonMapper,配置文件中与这两项无关的设置仍会保留。JsonMapperBuilderCustomizer 是 Spring Boot 4.0 起提供的自动配置扩展接口。接口文档

同一配置项发生冲突时,谁生效?

Spring Boot 自带 customizer 的执行顺序是 0。示例中的 @Order(1) 使这些设置在 Boot 的属性配置之后应用,因此:

  • ACCEPT_CASE_INSENSITIVE_PROPERTIES 最终被设置为 true。
  • mapper 的默认时区被设置为 TimeZone.getDefault()。
  • 如果 YAML 已经设置了 spring.jackson.time-zone,该值会被上述代码覆盖。

这符合原方法先应用配置文件、再追加代码设置的意图。同一个配置项不能同时保留两个不同的值;如果更晚执行的 customizer 再次修改该项,最终值也会随之改变。配置与执行顺序说明

如果希望由 YAML 决定这些设置

也可以直接配置属性名大小写不敏感:

spring:
  jackson:
    mapper:
      accept-case-insensitive-properties: true

时区可以通过 spring.jackson.time-zone 指定。例如,以下配置明确使用 Asia/Shanghai:

spring:
  jackson:
    mapper:
      accept-case-insensitive-properties: true
    time-zone: Asia/Shanghai

如果通过配置文件控制这两项,就删除 customizer 中对应的设置,避免代码再次覆盖它们。固定的 Asia/Shanghai 与 TimeZone.getDefault() 含义不同:后者取决于运行应用的 JVM 环境。

使用时注意

此方案以 Jackson 3 自动配置正常启用为前提。业务代码应注入 Spring 管理的 mapper;直接调用 new ObjectMapper() 或自行使用 JsonMapper.builder().build() 创建的实例,不会自动继承这些 Spring Boot 配置。

customizer 也不需要添加 @Primary,它参与配置过程,不会替换 mapper Bean。如果应用仍在使用 Jackson 2,需要使用对应的 Jackson 2 配置接口,不能混用两套类型。

备注:内容仅供参考。