首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何忽略JSON数组中的解码失败?

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

Stack Overflow用户
提问于 2018-06-05 04:19:06
回答 1查看 2.5K关注 0票数 8

假设我想用circe将JSON数组中的一些值解码为case类。下面的代码运行得很好:

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-shaped内容,这会导致解码错误:

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)))

我怎么能写一个解码器忽略数组中任何无法解码到case类中的东西呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-05 04:19:06

解决此问题的最直接方法是使用解码器,该解码器首先尝试将每个值解码为Foo,然后在Foo解码器失败时回退到标识解码器。circe 0.9中的新either方法使它的泛型版本实际上是一行程序:

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说“定义一个列表解码器,尝试使用给定的解码器来解码value".
  • Decoder[A].either(Decoder[Json]说的每个JSON数组”,首先尝试将值解码为A,如果失败,则将其解码为Json值(这将总是成功的),然后按照JSON所说的返回结果(如果有的话)“获取Either[A, Json]值的结果列表并删除所有JSON

…它以一种相当简洁的组合方式做了我们想要的事情。在某种程度上,我们可能想把它捆绑到circe本身的一个实用方法中,但现在写出这个显式版本还不算太差。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50688169

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档