Jackson Mixin配置defaultImpl无效:反序列化未知类型ID时抛出InvalidTypeIdException
如何让Jackson Mixin中的defaultImpl配置生效,处理未定义子类型的反序列化问题
我之前也碰到过一模一样的坑,你的问题核心在于:原抽象类Request上已经有了@JsonTypeInfo注解,而Jackson默认不会用Mixin的类级别注解替换原类的注解,只会做简单合并。原注解里没配置defaultImpl,所以哪怕你在Mixin里加了这个属性,也不会生效,导致遇到未知类型ID时直接抛出异常。
下面给你两种可行的解决方法,按需选择:
方法一:配置ObjectMapper让Mixin注解优先生效
如果没法修改原Request类的代码,你可以自定义一个注解内省器,让Jackson优先读取Mixin里的@JsonTypeInfo配置。用Kotlin实现的话代码如下:
val mapper = ObjectMapper() // 自定义注解内省器,先查Mixin的注解,再查原类的 val introspector = object : JacksonAnnotationIntrospector() { override fun findTypeInfo(config: MapperConfig<*>, aClass: Class<*>): JavaType? { val mixinClass = config.findMixInClassFor(aClass) ?: aClass val mixinTypeInfo = super.findTypeInfo(config, mixinClass) return mixinTypeInfo ?: super.findTypeInfo(config, aClass) } } mapper.setAnnotationIntrospector(introspector) // 别忘了注册你的Mixin mapper.addMixIn(Request::class.java, AlexaRequestMixin::class.java) // 记得加上JavaTimeModule处理OffsetDateTime mapper.registerModule(JavaTimeModule())
这个逻辑很简单:让Jackson在查找类型信息注解时,先检查对应的Mixin类,只有Mixin里没有相关注解时才会用原类的,这样Mixin里的defaultImpl就会生效了。
方法二:移除原类的@JsonTypeInfo,完全用Mixin配置
如果你有权限修改原Request类的代码,那最直接的方式就是把原类上的@JsonTypeInfo删掉,把所有类型信息配置都放到Mixin里:
修改后的Java基类:
@JsonSubTypes({@Type( value = InstallationError.class, name = "Alexa.DataStore.PackageManager.InstallationError" ), // 保留其他子类型配置 }) public abstract class Request { }
你的Mixin保持不变:
@JsonTypeInfo( use = Id.NAME, include = As.PROPERTY, property = "type", visible = true, defaultImpl = GenericRequest::class ) @JsonMixin(Request::class) class AlexaRequestMixin { }
然后正常注册Mixin到ObjectMapper就行,这时候Mixin的配置会完全接管类型解析,遇到未知的type值时,就会自动用GenericRequest来反序列化。
验证一下
你可以用这个测试JSON来验证:
{ "type": "Foo", "requestId": "test-abc-123", "timestamp": "2024-05-20T14:30:00Z" }
用配置好的ObjectMapper反序列化后,应该能得到一个完整的GenericRequest实例,不会再抛出InvalidTypeIdException啦。
内容的提问来源于stack exchange,提问作者pixel
相关产品推荐
相关产品推荐

