【问题标题】:Parsing a recursive trait playsafe json scala解析递归特征playsafe json scala
【发布时间】:2019-05-30 03:50:05
【问题描述】:

我正在使用 play-json_2.11,我正在尝试递归解析一些案例类

sealed trait Tree

case class Node(value: Float, child: Seq[Tree]) extends Tree

case class Leaf(leaf: Float) extends Tree

所以基本上,每个节点都包含一个值和一个树列表(可以是节点或叶子)。

所以我在案例类的伴随对象中定义了隐式读取器。对象中的一个名为Tree

object Node {
  implicit val reader = Json.reads[Node]
}

object Leaf {
  implicit val reader = Json.reads[Leaf]
}

object Tree {
  implicit val treeReads = 
    __.read[Node].map(x => x:Tree) orElse __.read[Leaf].map(x => x:Tree)
}

由于解析器相互引用,我无法定义它们并得到以下错误:

ScalaFiddle.scala:9: error: No instance of play.api.libs.json.Reads is available for scala.Seq[ScalaFiddle.Tree] in the implicit scope (Hint: if declared in the same file, make sure it's declared before)
implicit val reader = Json.reads[Node]

在这种情况下如何解析树? (我不需要它专门是一个特质)

这是我试过的小提琴https://scalafiddle.io/sf/sX8OkWI/3

我的输入是一个像这样的json

{
    "value": 1.0,
    "child": {
        "leaf": 2.0
    }
}

我想把它解析成有

Node(1.0, Leaf(2.0))

【问题讨论】:

  • 最新版play json直接支持Json.format宏中的密封族

标签: json scala parsing typesafe


【解决方案1】:

这就是你需要的

import play.api.libs.json._
import play.api.libs.functional.syntax._

sealed trait Tree


case class Node(value: Float, child: Tree) extends Tree
object Node {
  implicit lazy val reader = Json.reads[Node]
}

case class Leaf(leaf: Float) extends Tree
object Leaf {
  implicit lazy val reader = Json.reads[Leaf]
}

object Tree {
  implicit lazy val treeReads: Reads[Tree] = 
    __.lazyRead(Node.reader).map(x => x:Tree) orElse __.lazyRead(Leaf.reader).map(x => x:Tree)
}


val json: JsValue = Json.parse("""
{
    "value": 5.0,
    "child": {
      "leaf": 7
    }
}
""")


println(json)

json.validate[Tree] match {
  case s: JsSuccess[Tree] => {
    val place: Tree = s.get
    println(place)
  }
  case e: JsError => {
    println(e)
  }
}

【讨论】:

  • 不确定NodeLeaf 读取是否需要惰性
  • 是的。应该不会
  • Tree 添加隐式writes 的格式是什么?我有一个需要读写的用例。
【解决方案2】:

您不需要伴随对象中的隐含.. 或对象:

import play.api.libs.json._
import play.api.libs.functional.syntax._

sealed trait Tree

case class Node(value: Double, child: Tree) extends Tree
case class Leaf(leaf: Double) extends Tree

val json: JsValue = Json.parse("""
{
    "value": 1.0,
    "child": {
      "leaf": 2.0
    }
}
""")

implicit val nReader = Json.reads[Node]
implicit val lReader = Json.reads[Leaf]
implicit lazy val treeReads: Reads[Tree] = 
    __.lazyRead(nReader).map(x => x:Tree) orElse __.lazyRead(lReader).map(x => x:Tree)

json.validate[Tree] match {
  case s: JsSuccess[Tree] => {
    val place: Tree = s.get
    println(place)
  }
  case e: JsError => {
    println(e)
  }
}

https://scalafiddle.io/sf/sX8OkWI/13

【讨论】:

    猜你喜欢
    • 2018-05-29
    • 2011-05-05
    • 2018-09-30
    • 2022-01-07
    • 1970-01-01
    • 2012-01-17
    • 2021-05-25
    • 2012-10-04
    • 1970-01-01
    相关资源
    最近更新 更多