使用circe定义scala中的通用解码器

7ajki6be  于 2023-03-08  发布在  Scala
关注(0)|答案(2)|浏览(121)

我正尝试将JsonUtils类从Json4s切换到circe,我发现很难解决解码器的通用实现。
我Json4s函数如下所示:

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)

它运行得很好
现在,我已经尝试了相同的func与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

我在这里做错了什么?有没有一种方法来定义一个通用的解码器?我在这里读到了一些类似的问题,但还没有找到一个解决方案,适合我的需要

8i9zcol2

8i9zcol21#

您可以执行以下操作:

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"
mo49yndu

mo49yndu2#

这个答案Circe encoder for generic case class with default parameters with case class MyClass[T]使用泛型可能会有所帮助:

case class JsonParserCirce[T](implicit val lazyDecoder: Lazy[DerivedDecoder[T]]) {
  implicit val coderLocale: Coder[Locale] = Coder.kryo[Locale]
  implicit def defaultDecoder: Decoder[T] = deriveDecoder[T]

  def parseJSONStrings(
    messages: SCollection[String]
  )(implicit coder: Coder[T]): (SCollection[T], SCollection[JsonError]) = {
    log.info("Parsing JSON Strings...")
    val jsons: SCollection[Either[circe.Error, T]] = messages.map { s: String => json2CaseClass(s) }

/*My Transformations*/

// String to Json using Circe
  def json2CaseClass(jsonStr: String): Either[circe.Error, T] =
    decode(jsonStr)

相关问题