Как представить динамические ключи JSON в Scala при использовании circe - PullRequest
0 голосов
/ 08 января 2019

Я пытаюсь представить следующий 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 ]

0 голосов
/ 08 января 2019

Самый простой способ обработки такого случая, вероятно, состоит в том, чтобы заменить cars член класса Cars на тип, подобный 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.

0 голосов
/ 08 января 2019

Я думаю, вы можете просто использовать 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, если это требуется.

...