I have an array of Json objects. All of these objects follow one of two structures: The first like this:
{
"uuid": "321,
"uuidType": "series",
"title": "a movie",
"segments": [
"movie"
],
"seriesIds": [
"123"
]
}
And the second like this:
{
"uuid": "1234",
"uuidType": "programme",
"title": "programme title",
"type": "movie",
"segments": [
"movies"
],
"programmeIds": [
"321"
]
}
However, I want to parse these objects into the same case class like this:
case class SearchResult(uuid: String, uuidType: String, title: String, segments: List[String], ids: List[String])
So with the second type of object, the type key and value would be ignored, and both seriesIds from the first object and programmeIds from the second object would go into the ids part of the case class. However I have no idea how to do this! I am using Circe to decode/encode the json.
You can place a custom decoder in the SearchResult object companion
scala 2.12
circe 0.9.3
import io.circe._
import io.circe.parser._
object Main extends App {
val jsonA =
"""{
"uuid": "321",
"uuidType": "series",
"title": "a movie",
"segments": [
"movie"
],
"seriesIds": [
"123"
]
}"""
val jsonB =
"""{
"uuid": "1234",
"uuidType": "programme",
"title": "programme title",
"type": "movie",
"segments": [
"movies"
],
"programmeIds": [
"321"
]
}"""
case class SearchResult(uuid: String, uuidType: String, title: String, segments: List[String], ids: List[String])
object SearchResult {
implicit val decoder: Decoder[SearchResult] = Decoder.instance { h =>
for {
uuid <- h.get[String]("uuid")
uuidType <- h.get[String]("uuidType")
title <- h.get[String]("title")
segments <- h.get[List[String]]("segments")
ids <- {
h.getOrElse[List[String]]("seriesIds")(h.get[List[String]]("programmeIds").getOrElse(Nil))
}
} yield SearchResult(uuid, uuidType, title, segments, ids)
}
}
val obj1 = decode[SearchResult](jsonA)
println(obj1)
val obj2 = decode[SearchResult](jsonB)
println(obj2)
}