You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot升级2.7.0后自定义Jackson Module序列化器被忽略

问题根因

该问题由Spring Boot 2.3+版本对Jackson自动配置的两处默认逻辑调整导致,和2.2RELEASE版本行为存在兼容性差异:

  1. Module注册顺序变更:2.2版本中用户通过@Bean定义的Jackson Module会优先于框架内置模块加载,注册的序列化器匹配优先级更高;2.7版本中框架内置Jackson模块、Spring MVC预置的类型序列化器会先于普通用户Module注册,你绑定在Object.class上的通用序列化器会被前置的具体类型匹配规则拦截。
  2. 序列化匹配规则变更:Spring Boot 2.4+内置Jackson版本升级到2.11+,默认启用最具体类型优先匹配策略:序列化目标对象时,会优先查找该对象实际类型对应的序列化器,查找失败才会沿继承链向上匹配父类序列化器。同时Spring MVC 2.5+会为所有REST接口返回值类型提前注册默认Bean序列化器,匹配流程根本不会回溯到Object.class层级,因此你的自定义序列化器虽然随Module成功加载,但永远不会被触发。

你断点观察到自定义Module存在于模块列表中是正常现象,问题本质是序列化器的匹配优先级不够,不是Module没有被加载。

修复方案

按稳定性从高到低可选以下方案:

方案1:通过BeanSerializerModifier实现通用序列化拦截(推荐)

不要直接给Object.class注册序列化器,改用Jackson提供的序列化修改器扩展点,该扩展点不受版本匹配规则影响,兼容性最好:

@Configuration
public class JacksonConfig {
    @Bean
    public Module jacksonModule() {
        SimpleModule module = new SimpleModule();
        module.setSerializerModifier(new BeanSerializerModifier() {
            @Override
            public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> defaultSerializer) {
                Class<?> beanClass = beanDesc.getBeanClass();
                // 过滤不需要包装根节点的基础类型、框架内置类型
                if (shouldWrapRoot(beanClass)) {
                    // 传入原默认序列化器,避免递归序列化死循环
                    return new MyCustomSerializer(defaultSerializer);
                }
                return defaultSerializer;
            }
        });
        return module;
    }

    private boolean shouldWrapRoot(Class<?> clazz) {
        return !clazz.isPrimitive()
                && !Number.class.isAssignableFrom(clazz)
                && !CharSequence.class.isAssignableFrom(clazz)
                && !Boolean.class.isAssignableFrom(clazz)
                && !clazz.getPackage().getName().startsWith("org.springframework.")
                && !clazz.getPackage().getName().startsWith("com.fasterxml.");
    }
}

方案2:直接使用Jackson内置的根节点包装能力

你的需求是给JSON响应加根节点,不需要自定义序列化器,直接开启框架自带配置即可,稳定性最高:

  1. 在application.yml中添加配置:
spring:
  jackson:
    serialization:
      # 全局开启根节点包装
      wrap-root-value: true
  1. 对需要自定义根节点名称的返回类,添加@JsonRootName("自定义根节点名")注解即可,未加注解的类会默认使用类名首字母小写作为根节点名。

方案3:强制提升自定义Module的注册优先级

如果要完全保留原有直接注册Object.class序列化器的写法,不要直接注册Module Bean,改用Jackson2ObjectMapperBuilderCustomizer手动注入模块并设置最高优先级:

@Configuration
public class JacksonConfig {
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() {
        return builder -> {
            SimpleModule module = new SimpleModule();
            module.addSerializer(Object.class, new MyCustomSerializer());
            // 指定模块优先安装,优先级高于内置模块
            builder.modulesToInstall(module);
        };
    }
}

内容的提问来源于stack exchange,提问作者Shvalb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 20:39:21