我正在使用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))
答案 0 :(得分: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)
}
}
答案 1 :(得分:1)
您不需要伴随对象中的隐式对象..或与此相关的对象:
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)
}
}