在 Play for Scala 中序列化一棵树
Serializing a tree in Play for Scala
我有以下 class 这是一个树节点:
case class Node[A] ( id: Int, data: A, var children: Option[Seq[Node[A]]],
var parent: Option[Node[A]] )
其中id为节点id号,data表示节点存储的信息,children为子节点列表,parent为父节点
我想用树生成一个json,所以我写了下面的隐式val:
implicit val nodeWrite : Writes[Node[Data]] = (
(JsPath \ "sk").write[Int] and
(JsPath \ "dat").write[Data] and
(JsPath \ "ch").write[Option[Seq[Node[Data]]]] and
(JsPath \ "par").write[Option[Node[Data]]]
) (unlift(Node[Data].unapply))
但是编译器抱怨:
missing argument list for method apply in object Node Unapplied
methods are only converted to functions when a function type is
expected. You can make this conversion explicit by writing apply _ or
apply(,,,) instead of apply.
如何解决这个问题?
更新
数据定义为:
case class Data (descrip: String)
更新 2
因为我需要一棵有 N 个根的树,所以我创建了一个包含一系列节点的树 class。
case class Tree[A] ( var nodes: Option[Seq[Node[A]]] )
但是我在序列化树时遇到了问题:
implicit val treeWrite : Writes[Tree[Data]] = new Writes[Tree[Data]] {
def writes(x: Tree[Data]) = {
Json.obj(
"nodes" -> x.nodes.map(_.map(n => writes(n)))
)
}
}
它抛出
type mismatch; found : Option[Nothing] required:
play.api.libs.json.Json.JsValueWrapper
在 x.nodes.map
行。
我没有完整的答案,但你可以通过指定类型来帮助编译器:
(unlift[Node[Data],(Int, Data, Option[Seq[Node[Data]]], Option[Node[Data]])]
(Node.unapply[Data](_)))
但这对你没有帮助,因为你必须使用 lazyWrite
的递归类型。我建议在这里使用更明确的方法:
implicit val nodeWrite : Writes[Node[Data]] = new Writes[Node[Data]] {
def writes(x: Node[Data]) = {
Json.obj(
"id" -> x.id,
"data" -> x.data,
"children" -> x.children.map(_.map(n => writes(n))),
"parent" -> x.parent.map(n => writes(n)))
}
}
val child = Node(1, "child", None, None)
val node = Node(1, "data", Some(List(child)), None)
Json toJson node
res0: play.api.libs.json.JsValue = {"id":1,"data":"data",
"children":[{"id":1,"data":"child","children":null,"parent":null}],"parent":null}
添加空值处理,你会没事的。
我有以下 class 这是一个树节点:
case class Node[A] ( id: Int, data: A, var children: Option[Seq[Node[A]]],
var parent: Option[Node[A]] )
其中id为节点id号,data表示节点存储的信息,children为子节点列表,parent为父节点
我想用树生成一个json,所以我写了下面的隐式val:
implicit val nodeWrite : Writes[Node[Data]] = (
(JsPath \ "sk").write[Int] and
(JsPath \ "dat").write[Data] and
(JsPath \ "ch").write[Option[Seq[Node[Data]]]] and
(JsPath \ "par").write[Option[Node[Data]]]
) (unlift(Node[Data].unapply))
但是编译器抱怨:
missing argument list for method apply in object Node Unapplied methods are only converted to functions when a function type is expected. You can make this conversion explicit by writing apply _ or apply(,,,) instead of apply.
如何解决这个问题?
更新
数据定义为:
case class Data (descrip: String)
更新 2
因为我需要一棵有 N 个根的树,所以我创建了一个包含一系列节点的树 class。
case class Tree[A] ( var nodes: Option[Seq[Node[A]]] )
但是我在序列化树时遇到了问题:
implicit val treeWrite : Writes[Tree[Data]] = new Writes[Tree[Data]] {
def writes(x: Tree[Data]) = {
Json.obj(
"nodes" -> x.nodes.map(_.map(n => writes(n)))
)
}
}
它抛出
type mismatch; found : Option[Nothing] required: play.api.libs.json.Json.JsValueWrapper
在 x.nodes.map
行。
我没有完整的答案,但你可以通过指定类型来帮助编译器:
(unlift[Node[Data],(Int, Data, Option[Seq[Node[Data]]], Option[Node[Data]])]
(Node.unapply[Data](_)))
但这对你没有帮助,因为你必须使用 lazyWrite
的递归类型。我建议在这里使用更明确的方法:
implicit val nodeWrite : Writes[Node[Data]] = new Writes[Node[Data]] {
def writes(x: Node[Data]) = {
Json.obj(
"id" -> x.id,
"data" -> x.data,
"children" -> x.children.map(_.map(n => writes(n))),
"parent" -> x.parent.map(n => writes(n)))
}
}
val child = Node(1, "child", None, None)
val node = Node(1, "data", Some(List(child)), None)
Json toJson node
res0: play.api.libs.json.JsValue = {"id":1,"data":"data",
"children":[{"id":1,"data":"child","children":null,"parent":null}],"parent":null}
添加空值处理,你会没事的。