gpt4 book ai didi

json - 在使用 circe 解码 JSON 对象时捕获未使用的字段

转载 作者:行者123 更新时间:2023-12-04 01:55:46 24 4
gpt4 key购买 nike

假设我有一个像下面这样的 case 类,我想将一个 JSON 对象解码到其中,所有未使用的字段都以特殊成员的形式结束:

import io.circe.Json

case class Foo(a: Int, b: String, leftovers: Json)

在 Scala 中使用 circe 执行此操作的最佳方法是什么?

(注意:我见过这样的问题 a few times ,所以我正在为后代问答。)

最佳答案

有几种方法可以解决这个问题。一种相当直接的方法是过滤掉解码后使用的 key :

import io.circe.{ Decoder, Json, JsonObject }

implicit val decodeFoo: Decoder[Foo] =
Decoder.forProduct2[Int, String, (Int, String)]("a", "b")((_, _)).product(
Decoder[JsonObject]
).map {
case ((a, b), all) =>
Foo(a, b, Json.fromJsonObject(all.remove("a").remove("b")))
}

如您所愿:
scala> val doc = """{ "something": false, "a": 1, "b": "abc", "0": 0 }"""
doc: String = { "something": false, "a": 1, "b": "abc", "0": 0 }

scala> io.circe.jawn.decode[Foo](doc)
res0: Either[io.circe.Error,Foo] =
Right(Foo(1,abc,{
"something" : false,
"0" : 0
}))

这种方法的缺点是您必须维护代码以将您使用的 key 与其使用分开删除,这可能容易出错。另一种方法是使用 circe 的 state-monad-powered 解码工具:
import cats.data.StateT
import cats.instances.either._
import io.circe.{ ACursor, Decoder, Json }

implicit val decodeFoo: Decoder[Foo] = Decoder.fromState(
for {
a <- Decoder.state.decodeField[Int]("a")
b <- Decoder.state.decodeField[String]("b")
rest <- StateT.inspectF((_: ACursor).as[Json])
} yield Foo(a, b, rest)
)

它的工作方式与之前的解码器相同(除了解码失败时你会得到的错误的一些小差异):
scala> io.circe.jawn.decode[Foo](doc)
res1: Either[io.circe.Error,Foo] =
Right(Foo(1,abc,{
"something" : false,
"0" : 0
}))

后一种方法不需要您在多个地方更改使用的字段,而且它的优点是看起来更像您在 circe 中手动编写的任何其他解码器。

关于json - 在使用 circe 解码 JSON 对象时捕获未使用的字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51359889/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com