gpt4 book ai didi

json - 如何忽略 JSON 数组中的解码失败?

转载 作者:行者123 更新时间:2023-12-03 00:35:17 31 4
gpt4 key购买 nike

假设我想将 JSON 数组中的一些值解码为 circe 的案例类。以下工作正常:

scala> import io.circe.generic.auto._, io.circe.jawn.decode
import io.circe.generic.auto._
import io.circe.jawn.decode

scala> case class Foo(name: String)
defined class Foo

scala> val goodDoc = """[{ "name": "abc" }, { "name": "xyz" }]"""
goodDoc: String = [{ "name": "abc" }, { "name": "xyz" }]

scala> decode[List[Foo]](goodDoc)
res0: Either[io.circe.Error,List[Foo]] = Right(List(Foo(abc), Foo(xyz)))

有时,我正在解码的 JSON 数组包含其他非 Foo 形状的内容,但这会导致解码错误:

scala> val badDoc =
| """[{ "name": "abc" }, { "id": 1 }, true, "garbage", { "name": "xyz" }]"""
badDoc: String = [{ "name": "abc" }, { "id": 1 }, true, "garbage", { "name": "xyz" }]

scala> decode[List[Foo]](badDoc)
res1: Either[io.circe.Error,List[Foo]] = Left(DecodingFailure(Attempt to decode value on failed cursor, List(DownField(name), MoveRight, DownArray)))

如何编写一个解码器来忽略数组中无法解码到我的案例类中的任何内容?

最佳答案

解决此问题的最直接方法是使用解码器,该解码器首先尝试将每个值解码为 Foo ,然后如果 Foo 则回退到身份解码器解码器失败。新either circe 0.9 中的方法使得该方法的通用版本实际上是一行代码:

import io.circe.{ Decoder, Json }

def decodeListTolerantly[A: Decoder]: Decoder[List[A]] =
Decoder.decodeList(Decoder[A].either(Decoder[Json])).map(
_.flatMap(_.left.toOption)
)

它的工作原理如下:

scala> val myTolerantFooDecoder = decodeListTolerantly[Foo]
myTolerantFooDecoder: io.circe.Decoder[List[Foo]] = io.circe.Decoder$$anon$21@2b48626b

scala> decode(badDoc)(myTolerantFooDecoder)
res2: Either[io.circe.Error,List[Foo]] = Right(List(Foo(abc), Foo(xyz)))

分解步骤:

  • Decoder.decodeList说“定义一个列表解码器,尝试使用给定的解码器来解码每个 JSON 数组值”。
  • Decoder[A].either(Decoder[Json]说“首先尝试将值解码为 A ,如果失败,则将其解码为 Json 值(始终会成功),并将结果(如果有)作为 Either[A, Json] 返回”。<
  • .map(_.flatMap(_.left.toOption))表示“获取 Either[A, Json] 值的结果列表并删除所有 Right ”。

…它以相当简洁、组合的方式完成了我们想要的事情。在某些时候,我们可能希望将其捆绑到循环本身的实用方法中,但现在写出这个显式版本还不错。

关于json - 如何忽略 JSON 数组中的解码失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50688169/

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