Как представить динамические ключи JSON в Scala при использовании circe
Я пытаюсь представить следующий JSON как класс случая Scala:
{
"cars": {
"THIS IS A DYNAMIC KEY 1": {
"name": "bla 1",
},
"THIS IS A DYNAMIC KEY 2": {
"name": "bla 2",
}
...
}
Тем не менее, мой JSON имеет динамические ключи, которые я не буду знать во время выполнения, и я хотел бы использовать circe для кодирования / декодирования. Я использую правильный способ представить это с помощью Scala?
import io.circe.generic.JsonCodec
@JsonCodec
case class Cars(cars: List[Car])
@JsonCodec
case class Car(whatShouldThisBe: CarDetails) // Not sure how to represent this?
@JsonCodec
case class CarDetails(name: String)
2 ответа
Я думаю, что вы можете просто использовать Map[String, CarDetails]
, Ваша ADT становится:
import io.circe.generic.JsonCodec
@JsonCodec
case class Cars(cars: Map[String, CarDetails])
@JsonCodec
case class CarDetails(name: String)
Единственный сложный момент может быть, если вам требуется хотя бы один объект CarDetails или если ноль является приемлемым. Цирцея, кажется, поддерживает cats.data.NonEmptyMap
если это потребуется.
Самый простой способ справиться с таким делом, вероятно, это изменить cars
член Cars
класс case, чтобы иметь тип как Map[String, CarDetails]
опуская Car
кейс класс в целом. Если вы это сделаете, ваш код будет работать точно так же, как есть (минус Car
определение), и декодирует предоставленный вами пример JSON.
Если вы хотите что-то ближе к вашей структуре класса дел, вы можете сделать следующее:
import io.circe.Decoder
import io.circe.generic.JsonCodec
case class Cars(cars: List[Car])
object Cars {
implicit val decodeCars: Decoder[Cars] =
Decoder[Map[String, CarDetails]].prepare(_.downField("cars")).map(kvs =>
Cars(
kvs.map {
case (k, v) => Car(k, v)
}.toList
)
)
}
// I've added an `id` member here as a way to hold on to the JSON key.
case class Car(id: String, whatShouldThisBe: CarDetails)
@JsonCodec
case class CarDetails(name: String)
Это будет декодировать тот же JSON, но будет включать динамические ключи в Car
уровень.