I am using play-json_2.11, and I am trying to parse recursively some case classes
sealed trait Tree
case class Node(value: Float, child: Seq[Tree]) extends Tree
case class Leaf(leaf: Float) extends Tree
So basically, each Node contains a value and a list of Trees (which can be a Node or a Leaf).
So I am defining implicit readers in the companion objects of the case classes. and one in the object called 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)
}
As the parsers are referencing to each other, I cannot define them and get the following error:
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]
How can I parse a Tree in this case? (I do not need it to be specifically a Trait)
Here is the fiddle I tried https://scalafiddle.io/sf/sX8OkWI/3
My input is a json like this one
{
"value": 1.0,
"child": {
"leaf": 2.0
}
}
And I would like to parse it to have
Node(1.0, Leaf(2.0))
This is what you need
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)
}
}