【问题标题】:Deserializing nested polymorphic fields反序列化嵌套的多态字段
【发布时间】:2023-03-17 05:01:01
【问题描述】:

是否可以反序列化下面的JSON

{
  "operation": "create", // type discriminator
  "value": "some text",
  "source": {
    "name": "source name",
    "kind": "db" // type discriminator
  }
}

到下面的一组类

sealed trait Source

case class DbSource(name: String) extends Source

sealed trait Operation

case class CreateOperation(value: String, source: Source) extends Operation

在不借助自定义反序列化器的情况下使用 Json4s?

【问题讨论】:

标签: json scala json4s


【解决方案1】:

Json 库 Circe 提供您正在寻找的内容:The relevant page

implicit val sourceConfig: Configuration =
  Configuration.default.withDiscriminator("operation")

【讨论】:

    【解决方案2】:

    不知道 json4s,不过你可以用 jackson 来做: https://www.baeldung.com/jackson-inheritance

    【讨论】:

    • 这就是我现在正在使用的,但是使用自定义类型鉴别器字段设置多态反序列化非常难看。
    • @synapse 你的意思是注释 @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") 对我个人来说似乎可以接受,因为你不不必使用下面的子类型注释,您可以在我认为的 objectmapper 上注册这些子类型,因此它更具可扩展性。 @JsonSubTypes({ @Type(value = Car.class, name = "car"), @Type(value = Truck.class, name = "truck") }) 你说的丑是这个意思吗?
    • JSON 对象具有自定义命名的鉴别器字段和自定义值,因此我不得不创建 TypeIdResolver(实际上是三个)。无论如何,我已经通过切换到 scala-jsoniter 解决了这个问题,它更快并且具有反序列化 ADT 的优雅方式。
    【解决方案3】:

    使用 typeHint 字段 https://github.com/json4s/json4s#serializing-polymorphic-lists 您也可以更改此鉴别器字段名称,即:

    implicit val customFormats: Formats =
          new DefaultFormats {
            override val typeHintFieldName   = "className"
    

    这个例子对所有类型的特征使用字段类名->案例类。

    【讨论】: