Разобрать объекты Json в case-классы в Scala?
У меня есть массив объектов Json. Все эти объекты следуют одной из двух структур: Первая, как эта:
{
"uuid": "321,
"uuidType": "series",
"title": "a movie",
"segments": [
"movie"
],
"seriesIds": [
"123"
]
}
А второй вот так:
{
"uuid": "1234",
"uuidType": "programme",
"title": "programme title",
"type": "movie",
"segments": [
"movies"
],
"programmeIds": [
"321"
]
}
Тем не менее, я хочу разобрать эти объекты в один и тот же класс case следующим образом:
case class SearchResult(uuid: String, uuidType: String, title: String, segments: List[String], ids: List[String])
Таким образом, со вторым типом объекта ключ и значение типа будут игнорироваться, и оба seriesIds из первого объекта и programmeIds из второго объекта будут входить в часть id класса case. Однако я понятия не имею, как это сделать! Я использую Circe для декодирования / кодирования JSON.
2 ответа
Вы можете разместить собственный декодер в сопутствующем объекте SearchResult.
Скала 2.12
Цирцея 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)
}
Вы можете написать собственный код в circe, чтобы получить желаемый эффект, но мне кажется, было бы проще использовать автоматическую десериализацию circe и определить свой класс case как
case class SearchResult(uuid: String, uuidType: String, title: String, segments: List[String], programmeIds: Option[List[String]], seriesIds: Option[List[String]])
и преобразовать это в идентификаторы, используя простой код Scala