代码之家  ›  专栏  ›  技术社区  ›  Danny Thomas

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

  •  0
  • Danny Thomas  · 技术社区  · 5 年前

    我有一个模型,我无法控制在父对象中嵌套子类型,例如:

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

    现有的 EXTERNAL_PROPERTY

    1 回复  |  直到 5 年前
        1
  •  0
  •   Danny Thomas    5 年前

    AsPropertyTypeDeserializer

    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")
        }
    }