Определите generic c декодер в scala, используя circe - PullRequest
0 голосов
/ 16 февраля 2020

Я пытаюсь переключить свой класс JsonUtils с Json4s на circe, и мне трудно решить обобщенную c реализацию для декодера.

мой Json4s fun c выглядит так:

implicit val formats = DefaultFormats
  def extractValueFromJson[T](json: String, key: String)(implicit m: Manifest[T]): T = {
    val parsed = parse(json).asInstanceOf[JObject]
    val value =(parsed \ key).extract[T]
    value
  }

пример использования:

extractValueFromJson[String](jsonStr, keyInJson)

и он отлично работает

Теперь я попробовал такое же удовольствие c с Circe:

 implicit def decodeGeneric[A: Decoder](json: Json): Either[Error, A] = Decoder[A].decodeJson(json)
    def extractValueFromJson[A: ClassTag, T](jsonStr: String, key: String)(implicit m: Manifest[T]): T = {
            val json: String = jsonStr.asJson.noSpaces
            decode[A](json) match {
              case Left(error: Error) => throw error
              case Right(value) => {
                value.getClass.getDeclaredField(key).get(value).asInstanceOf[T] 
              }
            }
          }

и я получаю следующую ошибку при компиляции:

could not find implicit value for evidence parameter of type io.circe.Decoder[A]
[error]         decode[A](json) match {
[error]                  ^

Это желаемый вывод для данного ввода ввод:

case class Bar(str: String)
val bar = Bar("just a string")

использование:

val test = extractValueFromJson[Bar,String](bar.asJson.noSpaces,"str")

вывод:

just a string

Что я здесь не так делаю? Есть ли способ определить обобщенный c декодер? Я прочитал некоторые подобные вопросы здесь, но не нашел решения, которое бы соответствовало моим потребностям

1 Ответ

3 голосов
/ 16 февраля 2020

Вы можете сделать это:

def extractValueFromJson[A](jsonStr: String, key: String)(implicit decoder: Decoder[A]): A =
  io.circe.parser.decode(jsonStr)(decoder.at(field = key)) match {
    case Right(result) => result
    case Left(error) => throw error
  }

Что вы можете использовать следующим образом:

extractValueFromJson[String](jsonStr = bar.asJson.noSpaces, key = "str")
// res: String = "just a string"
...