[英]How to resolve recursive decoding in Circe when parsing Json?
我想使用 Circa 解析 JSON 字符串。 您可以在下面找到输入 JSON 的示例。
这是一种递归数据。 所以我的属性entity
包含实体的依赖关系。
我想解析对 map Map[String, Tasks]
的依赖关系。
{
"entity": [
{
"task_id": "X",
"type": "test",
"attributes": {
"name": "A",
"random_property_count": 1 // should be ignored
},
"dependencies": {
"random_name_1": {
"entity": [
{
"task_id": "907544AF",
"type": "test",
"attributes": {
"name": "B",
"random_attribute": "*"
},
"dependencies": {
"random_name_2": {
"entity": [
{
"task_id": "5",
"random_prop": "...", // should be ignored as it's not present in model
"type": "test",
"attributes": {
"name": "C"
}
}
]
}
}
}
]
}
}
}
]
}
这是我的代码:
case class Tasks (entity: Seq[Task])
case class Task(task_id: String, `type`: String, attributes: Attributes, dependencies: Map[String, Tasks])
case class Attributes(name: String)
implicit val decodeTask: Decoder[Task] = deriveDecoder[Task]
implicit val decodeTasks: Decoder[Tasks] = deriveDecoder[Tasks]
implicit val decodeAttributes: Decoder[Attributes] = deriveDecoder[Attributes]
val json = fromInputStream(getClass.getResourceAsStream("/json/example.json")).getLines.mkString
val tasks = decode[Tasks](json)
tasks match {
case Left(failure) => println(failure)
case Right(json) => println(json)
}
当我尝试将 JSON 字符串解析为 model 时,出现如下错误:
DecodingFailure(Attempt to decode value on failed cursor, List(DownField(dependencies), DownArray, DownField(entity), DownField(random_name_2), DownField(dependencies), DownArray, DownField(entity), DownField(random_name_1), DownField(dependencies), DownArray, DownField(entity)))
可能是什么问题?
DecodingFailure
的第二个成员在这种情况下很有用,因为它提供了失败之前成功操作的历史以及失败操作本身(按时间倒序排列,最近的在前)。 您可以像这样打印历史记录(或者只是在DecodingFailure
的字符串表示中检查它):
scala> import io.circe.DecodingFailure
import io.circe.DecodingFailure
scala> io.circe.jawn.decode[Tasks](doc) match {
| case Left(DecodingFailure(_, history)) => history.reverse.foreach(println)
| }
DownField(entity)
DownArray
DownField(dependencies)
DownField(random_name_1)
DownField(entity)
DownArray
DownField(dependencies)
DownField(random_name_2)
DownField(entity)
DownArray
DownField(dependencies)
如果您在文档中执行这些步骤直到最后一个,您将获得以下 object:
{
"task_id": "5",
"random_prop": "...",
"type": "test",
"attributes": {
"name": "C"
}
}
最后一步是失败的,它是DownField(dependencies)
,这是有道理的,因为这个 object 没有dependencies
项字段。
有几种方法可以解决此问题。 第一个是更改您的 JSON 表示,以便entity
数组中的每个 object 都有一个dependencies
项字段,即使它只是"dependencies": {}
。 如果您不想或无法更改 JSON,您可以将dependencies
项成员设为Option[Map[String, Tasks]]
(我刚刚确认这特别适用于您的情况)。 您还可以定义一个自定义Map
解码器,将缺失的字段解码为空 map,但这是一种更具侵入性的方法,我个人不推荐。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.