json Универсальный декодер со значениями по умолчанию с использованием scala с circe

Я столкнулся со странной ситуацией.
Я пытаюсь создать метод, который принимает тип и JSON и встраивает его в экземпляр класса case и, при необходимости, автоматически заполняет отсутствующие ключевые значения.
Пока мне удалось сделать все отдельно, но не вместе.
Класс case со значениями по умолчанию:

case class Foo(a: String = "empty String", b: Option[Int] = Some(1))

и когда я делаю преобразование:

import io.circe.generic.extras.auto._
import io.circe.generic.extras.Configuration
import io.circe.parser.decode
implicit val customConfig: Configuration = Configuration.default.withDefaults

println(decode[Foo]("{}"))

вот результат, который я получаю:

Right(Foo(empty String,Some(1)))

и это работает, как я ожидал

но когда я помещаю его в общий метод, он должен был быть вариантом из-за ошибки:

Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: DecodingFailure(Attempt to decode value on failed cursor, List(DownField(a)))

поэтому я меняю класс case на

case class Foo(a: Option[String] = Some("empty String"), b: Option[Int] = Some(1))

и добавляем декодер:

object Foo{
    implicit val decoder:Decoder[Foo] = deriveDecoder[Foo]
}

к методу:

import io.circe.Decoder
import io.circe.parser.decode

def convertToObj[T](jsonStr: String)(implicit decoder: Decoder[T]): T = { 
    decode[T](jsonStr)
    match {
      case Right(value) => value
      case Left(error) =>  throw error
    }
}
println(convertToObj[Foo]("{}"))

и вывод:

Foo(None,None)

так что теперь я потерял свои значения по умолчанию, которые я установил, и не могу использовать автоматический декодер.

Как мне объединить два моих желания в один подход?


person soosita    schedule 20.02.2020    source источник
comment
Что вы имеете в виду под: но когда я помещаю его в общий метод, он должен был быть вариантом из-за ошибки :? Какой общий метод? Понимаю ли я, что вы меняете свой класс из-за ошибки, которую вы получаете после помещения его в общий метод?   -  person michaJlS    schedule 20.02.2020
comment
вы правильно понимаете, я меняю класс, чтобы он работал, метод convertToObj [Foo] ({})   -  person soosita    schedule 20.02.2020


Ответы (1)


Вам нужно будет сделать что-то вроде:

package foo.bar

import io.circe.Decoder
import io.circe.generic.extras.semiauto
import io.circe.generic.extras.Configuration
import io.circe.parser.decode

case class Foo(a: String = "empty String", b: Option[Int] = Some(1))

object Foo {
  implicit val customConfig: Configuration = Configuration.default.withDefaults
  implicit val decoder: Decoder[Foo]       = semiauto.deriveConfiguredDecoder[Foo]
}

object TestApp extends App {
  def convertToObj[T](jsonStr: String)(implicit decoder: Decoder[T]): T =
    decode[T](jsonStr) match {
      case Right(value) => value
      case Left(error)  => throw error
    }

  println(convertToObj[Foo]("{}"))
}

Тем не менее, вы можете настроить Circe автоматически для получения вашего декодера, чтобы вы могли обойтись меньшим количеством шаблонов:

package foo.bar

import io.circe.Decoder
import io.circe.generic.extras.auto._
import io.circe.generic.extras.Configuration
import io.circe.parser.decode

case class Foo(a: String = "empty String", b: Option[Int] = Some(1))

object TestApp extends App {

  implicit val customConfig: Configuration = Configuration.default.withDefaults

  def convertToObj[T](jsonStr: String)(implicit decoder: Decoder[T]): T =
    decode[T](jsonStr) match {
      case Right(value) => value
      case Left(error)  => throw error
    }

  println(convertToObj[Foo]("{}"))
}

Оба этих примера дают мне результат: Foo(empty String,Some(1))

ЗАМЕТКА:

method deriveDecoder in object semiauto is deprecated (since 0.12.0): Use deriveConfiguredDecoder
person Damien O'Reilly    schedule 21.02.2020
comment
Спасибо за ответы и замечание. первый пример работает отлично, однако второй пример дает ошибку не удалось найти неявное значение для декодера параметра: io.circe.Decoder [Foo] при компиляции - person soosita; 23.02.2020
comment
Странно, у меня работает. Можете ли вы дважды проверить импорт. В частности, io.circe.generic.extras.auto._ Также я тестировал версию circe: 0.12.2. - person Damien O'Reilly; 24.02.2020
comment
я дважды проверил все .. но моя версия Circe 0.13.0 - person soosita; 24.02.2020