Scala circe декодирует тип Map[String, String]

У меня есть объект Map[String, String], который я хочу использовать как json. Я написал кодировщик для этого типа:

implicit val encodeMap: Encoder[Map[String, String]] = new Encoder[Map[String, String]] {
override def apply(values: Map[String, String]): Json = {
  values.toList
    .map(pair => Json.obj(
      (pair._1, pair._2.asJson)
    )).asJson
}
}

Помимо энкодера мне нужен декодер, но я понятия не имею, как его написать. Моя лучшая попытка на данный момент:

implicit val decodeMap: Decoder[Map[String, String]] = new Decoder[Map[String, String]] {
final def apply(c: HCurser): Decoder.Result[Map[String, String]] = ???

}

Довольно просто, но я действительно не знаю, как разобраться в этой проблеме.
Спасибо!


person Doe    schedule 10.10.2018    source источник
comment
Разве здесь не работает только import io.circe.generic.auto._ (позволяя вам использовать .asJson)?   -  person Andy Hayden    schedule 10.10.2018


Ответы (1)


Что-то вроде этого должно работать, но, как сказал Энди выше, в этом случае вы должны иметь возможность использовать автоматический или полуавтоматический вывод.

import cats.syntax.either._

implicit val decodeMap: Decoder[Map[String, String]] = new Decoder[Map[String, String]] {
  override def apply(c: HCursor): Decoder.Result[Map[String, String]] = {
    c.keys.fold[Decoder.Result[Map[String, String]]](Right(Map.empty))(
      _.foldLeft(Map[String, String]().asRight[DecodingFailure])((res, k) => {
        res.flatMap((m: Map[String, String]) => {
          c.downField(k).as[String].fold(
            _.asLeft[Map[String, String]],
            v => (m + (k -> v)).asRight[DecodingFailure]
          )
        })
      })
    )
  }
}
person Paul Medcraft    schedule 12.11.2018
comment
Моя версия без зависимости от кошек, едва протестированная и написанная до того, как я понял, что из-за неправильной конфигурации я не смог использовать встроенную: "nofollow noreferrer">gist.github.com/colindean/8ac20a7508565848ae8dc5729ab4d5b1 - person Colin Dean; 26.08.2020