繁体   English   中英

将“递归”对象转换为JSON(带有Scala的Play Framework 2.4)

[英]Converting “recursive” object to JSON (Play Framework 2.4 with Scala)

我已经达到了我的代码可以成功编译的地步,但是我对我的解决方案有疑问,并出于这个原因发布了这个问题。

我有一个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。 它还支持Writes [T]存在的任何T类​​型集合的Writes。

我需要指出,Node.getChildrenOf(node.id)从数据库返回一个节点列表。 因此,根据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

我在“写入”转换器中添加了“显式结果类型”,结果如下:

/** 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转换器的整体方法糟糕吗?

谢谢,对不起,很长的帖子。

问题出在"children" -> Node.getChildrenOf(node.id) Node.getChildrenOf(node.id)返回一个List[Node] Json.obj任何属性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)))
  )
}

至少可以编译,但是我还没有用任何数据对其进行过测试。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM