简体   繁体   中英

json4s - Partially deserialize to a case class

I have this JSON object

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

Which I'm trying to deserialize into a following case class:

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

addresses field in the above case class is sequence of String where as in actual JSON it's an array of objects. When I deserialize and serialize it back using:

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

I see: { "name":"Chaitanya", "addresses":[] }

Is there any way I can tell json4s to keep those json objects stringified and not to parse them. Where I can expect it to be array of stingified json objects:

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

Is there any way I can do it using custom serializer or type hint?

If you don't want them deserialized to a string you could always declare them as Json

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

Just leaving a better solution here that I ended up using. As @shane-delmore mentioned you can get away using Json/JsArray/JsObject/JsWhatever. If you don't want to use any JSON4S specific types in your case class definitions you can create the custom serializer:

// 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
))

Using the above custom serializer you can keep the part of JSON stringified

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

results in:

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

As expected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM