我已经达到了我的代码编译成功的程度,但我对我的解决方案有疑问,并且因为这个原因发布了这个问题。
我将Node类定义为:
case class Node(id: Long, label: String, parent_id: Option[Long])
我引用/取消引用递归的原因是因为从技术上讲,我不在节点中存储节点。相反,每个节点都有一个指向其父节点的指针,我可以说:给我所有Node id = X的子节点。
这是一个示例树,为了可视化。我想提供root_node的ID,并获得树转换为Json字符串:
root_node
|_ node_1
| |_ node_11
| |_ node_111
|_ node_2
|_ node_3
Json看起来像:
{"title": "root_node", "children": [...]}
子数组包含node_1,2和3等...递归地
以下是节点的Writes Converter:
/** json converter of Node to JSON */
implicit val NodeWrites = new Writes[Node] {
def writes(node: Node) = Json.obj(
"title" -> node.label,
"children" -> Node.getChildrenOf(node.id)
)
}
引用播放文档:
Play JSON API为大多数基本类型提供隐式写入,例如 如Int,Double,String和Boolean。它还支持Writes for 写入[T]存在的任何类型T的集合。
我需要指出Node.getChildrenOf(node.id)从DB返回一个节点列表。所以根据Play的文档,我应该能够将List [Node]转换为Json。似乎在Writes转换器本身中这样做会有点麻烦。
以下是运行此代码时产生的错误:
type mismatch;
found : List[models.Node]
required: play.api.libs.json.Json.JsValueWrapper
Note: implicit value NodeWrites is not applicable here because it comes after the application point and it lacks an explicit result type
我将“显式结果类型”添加到我的Writes转换器中,结果如下:
/** json converter of Node to JSON */
implicit val NodeWrites: Writes[Node] = new Writes[Node] {
def writes(node: Node) = Json.obj(
"title" -> node.label,
"children" -> Node.getChildrenOf(node.id)
)
}
现在代码正常执行,我可以在浏览器上显示树。
即使这看起来像是最干净的工作解决方案,IntelliJ仍然抱怨这条线:
"children" -> Node.getChildrenOf(node.id)
话说:
Type mismatch: found(String, List[Node]), required (String, Json.JsValueWrapper)
IntelliJ的错误报告可能不是基于Scala编译器吗?
最后,JSON转换器的整体方法是否可怕?
感谢并为这篇长篇文章感到抱歉。
答案 0 :(得分:1)
问题在于"children" -> Node.getChildrenOf(node.id)
。 Node.getChildrenOf(node.id)
会返回List[Node]
。而Json.obj
中的任何属性都需要JsValueWrapper
。在这种情况下,JsArray
。
这样的事情应该有效:
implicit val writes = new Writes[Node] {
def writes(node: Node) = Json.obj(
"title" -> node.label,
// Note that we have to pass this since the writes hasn't been defined just yet.
"children" -> JsArray(Node.getChildrenOf(node).map(child => Json.toJson(child)(this)))
)
}
这至少可以编译,但我没有用任何数据测试它。