【问题标题】:json4s - Partially deserialize to a case classjson4s - 部分反序列化为案例类
【发布时间】:2018-05-04 19:14:12
【问题描述】:

我有这个 JSON 对象

{
  "name": "Chaitanya",
  "addresses": [
    { "street": "20 ABC", "apt": "10" },
    { "street": "10 XYZ", "apt": "D3" }
  ]
}

我试图将其反序列化为以下案例类:

case class Person(
    name: Option[String] = None,
    addresses: Option[Seq[String]] = Some(Seq.empty)
)

addresses 上述案例类中的字段是字符串序列,而在实际 JSON 中,它是一个对象数组。当我反序列化并使用以下方法将其序列化时:

implicit val formats = Serialization.formats(NoTypeHints)
val parsed = parse(data).extractOpt[Person]
val str = write( parsed )

我明白了: { "name":"Chaitanya", "addresses":[] }

有什么方法可以告诉 json4s 将这些 json 对象字符串化而不是解析它们。我可以期望它是一个 stingified json 对象的数组:

{
  "name": "Chaitanya",
  "addresses": [
    "{\"street\":\"20 ABC\",\"apt\":\"10\"}",
    "{\"street\":\"10 XYZ\",\"apt\":\"D3\"}"
  ]
}

有什么方法可以使用自定义序列化程序或类型提示来实现吗?

【问题讨论】:

    标签: json scala jackson json4s


    【解决方案1】:

    如果您不希望将它们反序列化为字符串,您可以随时将它们声明为 Json

    case class Person(
        name: Option[String] = None,
        addresses: Option[Json/JsArray/JsObject/JsWhatever] =     Some(Seq.empty)
    )
    

    【讨论】:

      【解决方案2】:

      只是在这里留下一个我最终使用的更好的解决方案。正如@shane-delmore 提到的,您可以使用 Json/JsArray/JsObject/JsWhatever 摆脱困境。如果您不想在案例类定义中使用任何 JSON4S 特定类型,您可以创建自定义序列化程序:

      // Serializer
      // Converts JObject to stringified JSON blob
      val serializer: PartialFunction[JValue, String] = {
        case jObj: JObject =>
          implicit val formats = Serialization.formats(NoTypeHints)
          write(jObj)
      }
      
      // Deserializer
      // Converts String into JString
      val deserializer: PartialFunction[Any, JValue] = {
        case x: String => JString(x)
      }
      
      
      class JSONBlobSerializer extends CustomSerializer[String]( _ => (
       serializer,
       deserializer
      ))
      

      使用上面的自定义序列化程序,您可以将 JSON 的部分字符串化

      implicit val formats = Serialization.formats(NoTypeHints) + new JSONBlobSerializer()
      write( parse( data ).extract[Person] )
      

      结果:

      {
        "name": "Chaitanya",
        "addresses": [
          "{\"street\":\"20 ABC\",\"apt\":\"10\"}",
          "{\"street\":\"10 XYZ\",\"apt\":\"D3\"}"
        ]
      }
      

      正如预期的那样。

      【讨论】:

        最近更新 更多