【问题标题】:Best way to deserialize json objects based in property value根据属性值反序列化 json 对象的最佳方法
【发布时间】:2021-07-12 18:42:52
【问题描述】:

我想将 JSON 字符串转换为对象,我正在尝试找到最好的方法,因为这些对象非常相似,唯一的变化是它们之间的“数据”字段:

{
  "event_type": "REGISTER",
  "day": "2021-01-01",
  "data": {
    "name": "Kyore",
    "age": 10
  }
}

{
  "event_type": "DELETE",
  "day": "2021-01-01",
  "data": {
    "id": "1234-1234-1234",
    "reason": "user requested"
  }
}

这些事件作为 JSON 字符串来自 SQS 侦听器,我正在尝试找到使用 Kotlin 处理它们的最佳方法,但我不确定如何选择哪个类将在我的听众:

abstract class Event {
    abstract val event_type: String
    abstract val day: String
    abstract val data: EventData

    abstract class EventData
}

class RegisterEvent(
    override val eventType: String,
    override val day: String,
    override val data: RegisterData
) : Event() {

    data class RegisterData(
        val name: String,
        val age: Int
    ) : Event.EventData()
}

class DeleteEvent(
    override val eventType: String,
    override val day: String,
    override val data: DeleteData
) : Event() {

    data class RegisterData(
        val id: String,
        val reason: String
    ) : Event.EventData()
}

在正确的事件中转换消息字符串的最佳方法是什么?

【问题讨论】:

  • 您正在尝试做的事情称为polymorphic deserialization。它要求反序列化的目标类有一个共同的超类(最好是密封的)。阅读此主题:stackoverflow.com/a/64537173/421195
  • 看起来我的方法是正确的,但我不明白如何告诉杰克逊我的哪个类应该用于反序列化。
  • 所以我猜你没有读到足够远的内容来到达它说“你将不得不编写自定义 JsonContentPolymorphicSerializer 并将其连接到 Decomposed 类;你还必须为 StringValue 编写自定义序列化程序班级”。 PS:我使用 Java(不是 Kotlin),所以我真的不能就 Kotlin 的细节给你建议。 PPS:“Kotlin”让我想起了德语单词kotzen

标签: kotlin jackson


【解决方案1】:

在阅读了多态反序列化之后,我找到了使用 Kotlin 和 Jackson 的解决方案,基本上我们需要使用 jackson 注释中的 @JsonTypeInfo 和 @JsonSubTypes 并告诉它要检查哪个属性以进行反序列化以及哪个类应该在匹配时使用,使用 OP 示例:

data class Event(
   val event_type: String,
   val day: String,
   val data: EventData
) {

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "event_type", include = JsonTypeInfo.As.EXTERNAL_PROPERTY)
    @JsonSubTypes(value = [
        JsonSubTypes.Type(RegisterData::class, name = "REGISTER"),
        JsonSubTypes.Type(DeleteData::class, name = "DELETE")
    ])
   abstract class EventData
}

data class RegisterData(
    val name: String,
    val age: Int
) : Event.EventData()

data class DeleteData(
    val id: String,
    val reason: String
) : Event.EventData()

因此,当我们将 JSON 字符串转换为 Event 对象时,data 属性将映射到 RegisterDataDeleteData 类之一。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-24
    • 2011-09-23
    • 1970-01-01
    • 2014-03-02
    • 1970-01-01
    • 2012-06-08
    • 1970-01-01
    • 2011-07-09
    相关资源
    最近更新 更多