【问题标题】:json4s, how to deserialize json with FullTypeHints w/o explicitly setting TypeHintsjson4s,如何在不显式设置 TypeHints 的情况下使用 FullTypeHints 反序列化 json
【发布时间】:2020-07-16 22:28:06
【问题描述】:

我确实在反序列化之前指定了 FullTypeHints

 def serialize(definition: Definition): String = {
    val hints = definition.tasks.map(_.getClass).groupBy(_.getName).values.map(_.head).toList
    implicit val formats = Serialization.formats(FullTypeHints(hints))
    writePretty(definition)
  }

它生成带有类型提示的 json,太棒了!

{
  "name": "My definition",
  "tasks": [
    {
      "jsonClass": "com.soft.RootTask",
      "name": "Root"
    }
  ]
}

反序列化不起作用,它会忽略带有类型提示的“jsonClass”字段


  def deserialize(jsonString: String): Definition = {
    implicit val formats = DefaultFormats.withTypeHintFieldName("jsonClass")
    read[Definition](jsonString)
  }

如果提示在 json 字符串中,为什么我应该使用 Serialization.formats(FullTypeHints(hints)) 重复 typeHints 以进行反序列化?

json4s 可以从 json 中推断出来吗?

【问题讨论】:

标签: scala serialization deserialization json4s


【解决方案1】:

反序列化器不会忽略类型提示字段名称,它只是没有任何东西可以映射它。这就是提示的来源。因此,您必须再次声明和分配提示列表对象,然后通过使用 withHints 方法或在创建 DefaultFormats 的新实例时覆盖该值将其传递给 DefaultFormats 对象。这是使用后一种方法的示例。

val hints = definition.tasks.map(_.getClass).groupBy(_.getName).values.map(_.head).toList
implicit val formats: Formats = new DefaultFormats {
    outer =>
        override val typeHintFieldName = "jsonClass"
        override val typeHints = hints
}

【讨论】:

  • 同意,它适用于显式设置。我很惊讶我无法将“typeHintFieldName”和“FullTypeHints”设置为反序列化器。将 json 映射到具体的类实例就绰绰有余了
【解决方案2】:

自从我有合同以来,我就这样做了:

  • withTypeHintFieldName是提前知道的
  • withTypeHintFieldName 包含完全限定的类名,它始终是案例类
def deserialize(jsonString: String): Definition = {
    import org.json4s._
    import org.json4s.native.JsonMethods._
    import org.json4s.JsonDSL._
    val json = parse(jsonString)
    val classNames: List[String] = (json \\ $$definitionTypes$$ \\ classOf[JString])
    val hints: List[Class[_]] = classNames.map(clz => Try(Class.forName(clz)).getOrElse(throw new RuntimeException(s"Can't get class for $clz")))

    implicit val formats = Serialization.formats(FullTypeHints(hints)).withTypeHintFieldName($$definitionTypes$$)
    read[Definition](jsonString)

【讨论】:

    最近更新 更多