我有以下自引用(递归)类:
class Node {
String label
// other attributes go here
static belongsTo = [parent: Node]
static hasMany = [children: Node]
static constraints = {
label blank: false
parent nullable: true
children nullable: true
}
}
我在BootStrap.groovy中使用了一个marshaller,因为我只想将一些select属性发送到客户端,在这个阶段只有标签:
JSON.registerObjectMarshaller(Node) { Node node ->
return [label: node.label, items: node.children]
}
创建节点层次结构,例如:
def parent1 = new Node(label: "Node 1").save(flush: true)
parent1.addToChildren(new Node(label: "Node 1.1"))
def parent2 = new Node(label: "Node 2").save(flush: true)
def child21 = new Node(label: "Node 2.1")
child21.addToChildren(new Node(label: "Node 2.1.1"))
parent2.addToChildren(child21)
并将其列为:
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond Node.list(params), model: [nodeInstanceCount: Node.count()]
}
我想要这样的东西:
Node 1
|
-- Node 1.1
Node 2
|
-- Node 2.1
|
-- Node 2.1.1
结果看起来很有希望,但有一些节点太多了:
Node 1
|
-- Node 1.1
Node 2
|
-- Node 2.1
|
-- Node 2.1.1
Node 1.1
Node 2.1
|
-- Node 2.1.1
Node 2.1.1
输出是不受欢迎的,但有意义:对于每个节点,都会调用此方法,因此需要额外的层次结构/单个节点。
我尝试解决此问题的一种方法是添加一个“处理过的”#39;属性进入Node类。这具有期望的效果(每个节点仅处理一次导致所需的层次结构)但是引入了此后必须管理该状态变量的问题。因此,我想避免这种黑客攻击。 另一种方法是让客户处理收到的数据
有没有一种简单的方法可以解决这个问题?
答案 0 :(得分:1)
在发布上述问题后,我找到了罪魁祸首。我希望有一天能帮到某人,以防他们遇到类似的问题。
当我们想要的只是顶级节点时, Node#list
显然会返回所有节点:
respond Node.list(params), model: [nodeInstanceCount: Node.count()]
直接跳到答案,以下解决了这个问题:
isRoot
属性
然后将index()
更改为以下内容:
respond Node.findAllByIsRoot(true), model: [nodeInstanceCount: Node.count()]
提供更多详情:
marshaller用于将此数据转换为所需的JSON格式(由#respond
方法决定,例如,查看ACCEPT
或CONTENT-TYPE
标头,或者就像在这种情况下查看请求URI中的format
字段(如UrlMappings#mappings
中所定义))将是
org.codehaus.groovy.grails.web.converters.marshaller.json.CollectionMarshaller
因此对于列表中的每个对象,marshaller都会被调用
收集编组然后委托给伴随的转换器,在我们的例子中是
类型<强> grails.converters.JSON 强>
在JSON#value
方法中,当我们注册我们的编组时,它最终会调用BootStrap.groovy
类中定义的闭包