Kotlin 如何从父对象确定Jackson多态反序列化的类型

Kotlin 如何从父对象确定Jackson多态反序列化的类型,kotlin,jackson,Kotlin,Jackson,我有一个模型,不控制将子类型嵌套在父类中的模型,例如: { timestamp: 0, type: { eventType: "Foo" majorVersion: 1 minorVersion: 0 }, data: { foo: "baz" } } 现有的EXTERNAL\u属性类型解析器只能处理字符串字段,不能处理对象。自动应答,因为我发现这很难理解。使用自定义的AsPropertyType

我有一个模型,不控制将子类型嵌套在父类中的模型,例如:

{
  timestamp: 0,
  type: {
     eventType: "Foo"
     majorVersion: 1
     minorVersion: 0
  },
  data: {
    foo: "baz"
  }
}

现有的
EXTERNAL\u属性
类型解析器只能处理字符串字段,不能处理对象。

自动应答,因为我发现这很难理解。使用自定义的
AsPropertyTypeDeserializer
。Kotlin通过自动注册密封的类子类型而不需要注释,并将未知类型处理作为额外的好处,从而简化了这一过程:

class Event(
    override val timestamp: Long,
    val type: EventType,
    @JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "type",
        visible = true
    )
    @JsonTypeResolver(EventDataTypeResolverBuilder::class)
    val data: EventData
)

class EventType(
    val majorVersion: Int,
    val minorVersion: Int,
    val eventType: String
)

sealed class EventData {
    data class Foo(
        val foo: String
    ) : EventData()

    data class Bar(
        val bar: String
    ) : EventData()

    object Unknown: EventData()
}

class EventDataTypeResolverBuilder : StdTypeResolverBuilder() {
    override fun buildTypeDeserializer(
        config: DeserializationConfig,
        baseType: JavaType,
        subtypes: MutableCollection<NamedType>,
    ): TypeDeserializer {
        val idRes = idResolver(
            config,
            baseType,
            subTypeValidator(config),
            subtypes,
            false,
            true
        )
        return EventDataTypeDeserializer(
            baseType,
            idRes,
            _typeProperty,
            _typeIdVisible,
            null
        )
    }
}

class EventDataTypeDeserializer : AsPropertyTypeDeserializer {
    constructor(
        bt: JavaType,
        idRes: TypeIdResolver,
        typePropertyName: String,
        typeIdVisible: Boolean,
        defaultImpl: JavaType?,
    ) : super(bt, idRes, typePropertyName, typeIdVisible, defaultImpl)

    constructor(src: EventDataTypeDeserializer, property: BeanProperty) : super(src, property)

    override fun forProperty(prop: BeanProperty): TypeDeserializer {
        return if (prop === _property) this else EventDataTypeDeserializer(this, prop)
    }

    @Throws(IOException::class)
    override fun deserializeTypedFromObject(p: JsonParser, ctxt: DeserializationContext): Any? {
        val type = p.parsingContext.parent.currentValue as EventType
        val typeId = "EventData\$${type.eventType}"
        return _findDeserializer(ctxt, typeId).deserialize(p, ctxt)
    }

    override fun _handleUnknownTypeId(ctxt: DeserializationContext, typeId: String): JavaType {
        return _idResolver.typeFromId(ctxt, "EventData\$Unknown")
    }
}

类事件(
覆盖val时间戳:长,
val类型:EventType,
@JsonTypeInfo(
use=JsonTypeInfo.Id.NAME,
include=JsonTypeInfo.As.PROPERTY,
property=“type”,
可见=真
)
@JsonTypeResolver(EventDataTypeResolverBuilder::类)
val数据:事件数据
)
类事件类型(
val majorVersion:Int,
val minorVersion:Int,
val eventType:String
)
密封类事件数据{
数据类Foo(
瓦尔福:字符串
):EventData()
数据类栏(
值栏:字符串
):EventData()
对象未知:EventData()
}
类EventDataTypeResolverBuilder:StdTypeResolverBuilder(){
重写buildTypeDeserializer(
配置:反序列化配置,
baseType:JavaType,
子类型:可变集合,
):类型反序列化器{
val idRes=idResolver(
配置,
基本类型,
子验证程序(配置),
亚型,
假,,
真的
)
返回EventDataTypeDeserializer(
基本类型,
伊德里斯,
_类型属性,
_typeIdVisible,
无效的
)
}
}
类EventDataTypeDeserializer:AsPropertyTypeDeserializer{
建造师(
bt:JavaType,
idRes:TypeIdResolver,
typePropertyName:字符串,
typeIdVisible:Boolean,
defaultImpl:JavaType?,
):super(bt、idRes、typePropertyName、typeIdVisible、defaultImpl)
构造函数(src:EventDataTypeDeserializer,属性:BeanProperty):super(src,属性)
重写fun-forProperty(prop:BeanProperty):类型反序列化器{
如果(prop===\u属性)此else EventDataTypeDeserializer(此,prop)返回
}
@抛出(IOException::类)
重写有趣的反序列化TypedFromObject(p:JsonParser,ctxt:DeserializationContext):有吗{
val type=p.parsingContext.parent.currentValue作为事件类型
val typeId=“EventData\${type.eventType}”
return\u findDeserializer(ctxt,typeId)。反序列化(p,ctxt)
}
重写fun\u handleUnknownTypeId(ctxt:DeserializationContext,typeId:String):JavaType{
返回_idResolver.typeFromId(ctxt,“EventData\$Unknown”)
}
}