【问题标题】:Jackson/Spring deserialization with generic sub classes具有通用子类的 Jackson/Spring 反序列化
【发布时间】:2026-02-13 02:55:02
【问题描述】:

首先我使用的是 kotlin 和 spring。

我想要做的是有一个过滤器基类/抽象类/接口,它基本上什么都没有。它应该有两个孩子,每个孩子都有自己的属性。让我展示一些代码:

 abstract class AxisFilter<T : Comparable<T>>()

data class SingleAxisFilter<T : Comparable<T>>(
        val value: T,
        val isAbove: Boolean?,
        val isMatch: Boolean
) : AxisFilter<T>()

data class DualAxisFilter<T : Comparable<T>>(
        val lowerBound: T,
        val upperBound: T,
        val isBetween: Boolean,
        val inclusive: Boolean = true
) : AxisFilter<T>()

我写了一个序列化器:

class AxisFilterDeserializer<T : Comparable<T>> : JsonDeserializer<AxisFilter<T>>() {
  override fun deserialize(jsonParser: JsonParser, deserializationContext: DeserializationContext): AxisFilter<T> {
    val oc: ObjectCodec = jsonParser.getCodec()
    val node: JsonNode = oc.readTree(jsonParser)

    return if(node.has("lowerBound"))
      DualAxisFilter<T>(
              lowerBound = node.get("lowerBound") as T,
              upperBound = node.get("upperBound") as T,
              isBetween = node.get("isBetween") as Boolean,
              inclusive = if(node.has("inclusive")) node.get("inclusive") as Boolean else true)
    else
        SingleAxisFilter<T>(
                value = node.get("value") as T,
                isAbove = if(node.has("isAbove")) node.get("isAbove") as Boolean else null,
                isMatch = node.get("isMatch") as Boolean
        )
  }
}

并尝试使用 @JsonDeserialize 注释,但它不起作用 - 或者我似乎无法让它起作用。

@Type(value = SingleAxisFilter)@Type(value = DualAxisFilter) 也因为泛型而失败。

希望有人能帮我解决这个问题。

【问题讨论】:

    标签: java spring jackson kotlin json-deserialization


    【解决方案1】:

    原来你只需要这样做:

    @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
        abstract class AxisFilter<T : Comparable<T>>()
    
        class SingleAxisFilter<T : Comparable<T>>(
                val value: T,
                val isAbove: Boolean?,
                val isMatch: Boolean
        ) : AxisFilter<T>()
    
        class DualAxisFilter<T : Comparable<T>>(
                val lowerBound: T,
                val upperBound: T,
                val isBetween: Boolean,
                val inclusive: Boolean = true
        ) : AxisFilter<T>()
    

    然后在 JSON 请求对象中,您必须提供带有完整路径的 @class 属性:

    {
        "value": 5.0,
        "isMatch": true,
        "isAbove": null,
        "@class": "com.blbla.common.SingleAxisFilter"
    }
    

    【讨论】: