Spring Boot 4 的 JSON 配置没生效
Spring Boot 4 按 JsonMapper 类型决定是否创建默认 JSON mapper。已有 Bean 声明返回 ObjectMapper 时,自定义配置可能存在却没有被 HTTP 转换器采用。
升级 Spring Boot 4 后,自定义的 JSON 模块没有应用到 HTTP 响应,但单独调用自己的 mapper 又能得到正确结果。已有 @Bean 方法如果声明返回 ObjectMapper、实际构造的是 JsonMapper,应检查自动配置是否又创建了另一份 mapper。
这里针对 Spring Boot 4 的 Jackson 3 JSON 自动配置。它按 JsonMapper 类型判断是否退让;返回类型仍声明为更宽的 ObjectMapper 时,不能只凭运行时对象是其子类,就认定自动配置已经识别并停用了默认 mapper。
先确认应用实际用了哪一份 mapper
检查配置类是否已经被扫描或导入,再查看容器中的 mapper Bean 名称、声明类型与 @Primary 状态。随后核对 MVC 或自定义消息转换器实际选择的实例。
Spring Boot 4 的默认 JSON mapper 是 JsonMapper,自动配置方法带有 @Primary 和 @ConditionalOnMissingBean。条件没有另外指定类型时,使用的是该 Bean 方法的返回类型。因此可能出现两份对象:自定义 Bean 已经存在,但默认的 JsonMapper 仍然创建,并继续被优先使用。
这与配置类完全没有注册不同。若根本看不到自定义 Bean,应先处理扫描或导入问题;若配置了自己的转换器,还应核对它的选择逻辑,不能仅修改方法声明就判断所有 JSON 入口都已切换。
修改已有方法声明,保留原配置内容
在确认方法构造的确实是 Jackson 3 的 JsonMapper 后,把已有 Bean 方法的声明返回类型改成它。下面仅展示声明的差异,不是新增第二个 Bean,也不替换原方法体:
- ObjectMapper objectMapper() {
+ JsonMapper objectMapper() {
对应类型是 tools.jackson.databind.json.JsonMapper。这里的 Jackson 3 ObjectMapper 属于 tools.jackson.databind;Jackson 2 的 com.fasterxml.jackson.databind.ObjectMapper 不能混进这份替换规则。
原来的模块注册、特性设置和构造过程应保留。只在返回表达式上强制转换、却继续把方法声明为 ObjectMapper,没有解决自动配置读取 Bean 类型信息的这一问题。再加一个 @Primary 也可能留下竞争的 mapper,增加其他 JSON 消费者的歧义。
如果只想调整一项格式或特性,可另评估对应版本的 builder customizer 或模块集成方式。但那是不同的配置方案,需要核对接口和应用默认设置,不能用一份空 mapper 替换掉原有模块来“修复”。
验收需要经过真实 HTTP 序列化
用项目已有的、能体现自定义模块行为的请求和响应检查处理结果。直接调用 Bean 得到正确 JSON,只证明那份对象的配置存在,不能证明 HTTP 转换器正在使用它。
确认预期的默认 mapper 已退让、实际选择的 Bean 正确,再检查其他 JSON 入口的日期、枚举、字段命名及反序列化约定是否仍符合要求。此次变更可能影响全局 JSON 行为,应保留配置差异和原来的回归样例。
需要撤回时恢复原方法声明与相应配置,或回到此前审定且依赖兼容的应用版本。不要为了让一个接口恢复,再加入另一份相互竞争的默认 mapper。


