使用 Jackson JsonDeserializer 解码自定义对象

Decode custom object using Jackson JsonDeserializer

我是 Kotlin 的新手(来自 Swift),我有一个非常简单的 json,我需要将其解码为两个不同的 Kotlin class 基于一个字段json。如果字段是"type": "Square"我想解码一个Squareclass,如果字段是"type": "Rectangle",我想解码一个Rectangleclass .

我需要解码的json是

{
  "type": "Square",
  "size": "1"
}

{
  "type": "Rectangle",
  "width": 1,
  "length": 2
}

我的 .kt class 是这样定义的。我写了一个自定义 JsonDeserializer 但它似乎不起作用,因为 jp.readValueAs(Square::class.java) 返回 null。

@JsonDeserialize(using = Shape.Deserializer::class)
sealed class Shape {
    enum class Type {
        Rectangle,
        Square
    }

    abstract val type: Type

    data class Square(
        val size: Int
    ) : Shape() {
        override val type: Type = Type.Square
    }

    data class Rectangle(
        val width: Int,
        val length: Int
    ) : Shape() {
        override val type: Type = Type.Rectangle
    }

    class Deserializer: JsonDeserializer<Shape>() {
        override fun deserialize(jp: JsonParser, ctxt: DeserializationContext?): Shape {
            var node = jp.readValueAsTree<JsonNode>()
            return when(node.get("type").asText()) {
                Type.Square.name ->
                    jp.readValueAs(Square::class.java)
                Type.Rectangle.name ->
                    jp.readValueAs(Rectangle::class.java)
                else -> throw JsonMappingException("")
            }
        }
    }
}

我做错了什么?

干杯

回答我自己的问题:我认为可以使用 Shape class 上的注释打开 type 属性,如下所示

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
@JsonSubTypes(
    value = [
        JsonSubTypes.Type(value = Shape.Square::class, name = "Square"),
        JsonSubTypes.Type(value = Shape.Rectangle::class, name = "Rectangle")
    ]
)
sealed class Shape {
    enum class Type {
        Rectangle,
        Square
    }
    abstract val type: Type
    data class Square(
        val size: Int
    ) : Shape() {
        override val type: Type = Type.Square
    }

    data class Rectangle(
        val width: Int,
        val length: Int
    ) : Shape() {
        override val type: Type = Type.Rectangle
    }
}