在Scala中使用circe解析含嵌套列表的递归JSON结构
基于circe的嵌套混合递归JSON结构解析方案
第一步:定义递归代数数据类型(ADT)
首先我们需要定义和JSON结构匹配的递归类型,覆盖args字段所有可能的取值形式:
sealed trait ArgEntry // 对应单个节点对象 case class Node(name: String, args: List[ArgEntry]) extends ArgEntry // 对应嵌套的列表结构 case class NestedArgs(items: List[ArgEntry]) extends ArgEntry
第二步:实现递归解码器
因为类型是递归引用的,所以需要用惰性求值的解码器避免初始化顺序问题,同时用or组合两种解码分支,优先匹配节点对象,匹配失败再尝试解析为嵌套列表:
import io.circe._ import io.circe.generic.semiauto._ import io.circe.parser._ object RecursiveJsonParser { implicit lazy val nodeDecoder: Decoder[Node] = deriveDecoder[Node] implicit lazy val argEntryDecoder: Decoder[ArgEntry] = nodeDecoder.widen[ArgEntry] or Decoder.decodeList(argEntryDecoder).map(NestedArgs).widen[ArgEntry] }
第三步:测试解析效果
直接调用circe的解析API即可处理你给出的所有混合嵌套场景:
def main(args: Array[String]): Unit = { val targetJson = """{ "name": "xx", "args": [ {"name":"xy", "args": []}, [ {"name":"xy", "args": []}, {"name":"xy", "args": [[]]} ], [ [ {"name":"xy", "args": [{"name":"xy", "args": []}]} ] ] ] }""" val parseResult = parse(targetJson).flatMap(_.as[Node]) // 解析成功会返回Right包裹的Node实例,所有嵌套结构都会被正确映射 println(parseResult) }
可选:实现序列化编码器
如果需要将Scala结构转回JSON,可以按同样逻辑实现编码器:
implicit lazy val nodeEncoder: Encoder[Node] = deriveEncoder[Node] implicit lazy val argEntryEncoder: Encoder[ArgEntry] = Encoder.instance { case n: Node => nodeEncoder(n) case NestedArgs(items) => Encoder.encodeList(argEntryEncoder).apply(items) }
内容的提问来源于stack exchange,提问作者fr3ak
相关产品推荐
相关产品推荐

