SpringBoot中@JsonComponent无法识别、自定义反序列化器不生效
问题现象
使用@JsonComponent标注自定义反序列化类实现JSON入参反序列化,即使手动注册该类,接口传入对应入参时反序列化逻辑仍未触发。
当前项目与可正常运行的POC环境核心差异:
- 引入
openapi-generator-maven-plugin生成Controller代码 - 采用AspectJ实现编译期织入
初步怀疑openapi代码生成逻辑导致Controller调用流程中反序列化器无法被正常识别。
相关代码
自定义反序列化器实现:
@JsonComponent public class UserDeserializer extends JsonDeserializer<User> { @Override public User deserialize (JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { log.info("***********INVOKED***************"); TreeNode treeNode = jsonParser.getCodec().readTree(jsonParser); ObjectMapper objectMapper = new ObjectMapper(); // 自定义业务逻辑 } }
手动注册反序列化器的Bean配置:
@Bean public Module userDeserializer() { SimpleModule module = new SimpleModule(); module.addDeserializer(User.class, new UserDeserializer()); return module; }
问题根因
AspectJ编译期织入不会影响Jackson反序列化器的正常识别,核心问题出在openapi-generator-maven-plugin的生成逻辑上
- AspectJ编译期织入仅做字节码增强,不会改动Spring容器的Bean注册流程,也不会替换Jackson核心序列化组件,只要自定义反序列化器被正常注册到接口实际使用的ObjectMapper中,就不会被织入逻辑干扰。
- openapi-generator默认生成的Controller代码,会自动配置独立的
HttpMessageConverter,多数场景下会单独实例化全新的ObjectMapper对象,不会复用Spring容器中你注册了自定义反序列化器的全局ObjectMapperBean,导致你注册的反序列化器根本没有被加载到接口实际使用的序列化工具链中。 - 部分版本的openapi-generator生成的Spring接口,会默认跳过Spring MVC原生的参数解析流程,使用内置的Jackson配置做入参转换,自然不会触发你自定义的反序列化逻辑。
- 代码存在两处配置隐患:
- 同时使用
@JsonComponent自动扫描注册和手动注册SimpleModule两种方式注册同类型反序列化器,部分Jackson版本下会出现注册覆盖、匹配跳过的问题 - 在
deserialize方法内部手动new了全新的ObjectMapper实例,该实例完全独立,不会继承任何全局配置,即使反序列化入口触发,后续用这个实例做转换也会出现配置不生效的问题
- 同时使用
修复方案
- 第一步:确认接口实际使用的
ObjectMapper实例。在Controller方法中注入MappingJackson2HttpMessageConverter,打印其持有的ObjectMapper中注册的反序列化器列表,确认是否存在UserDeserializer,如果不存在即可证明接口使用的不是你自定义配置的全局ObjectMapper。 - 第二步:调整openapi-generator插件配置,生成代码时开启
delegatePattern=true参数,对应SpringBoot3环境额外开启useSpringBoot3=true,关闭生成代码自带的ObjectMapper配置,强制生成的Controller复用Spring全局的消息转换器。 - 第三步:清理重复注册逻辑,
@JsonComponent和手动注册SimpleModule二选一即可;删除反序列化方法内部手动new的ObjectMapper,直接使用jsonParser.getCodec()返回的ObjectCodec完成后续树转对象操作,避免独立实例导致配置丢失。 - 第四步:如果不想修改插件配置,可以自定义
RequestMappingHandlerAdapter,强制替换生成Controller加载的HttpMessageConverter中持有的ObjectMapper为全局配置的实例。
内容的提问来源于stack exchange,提问作者user3310115
相关产品推荐
相关产品推荐

