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 配置接口,不能混用两套类型。
备注:内容仅供参考。
