29

我有两个域类,一个是父类,另一个是子类,它们之间有一个 hasMany 关系。父类有很多子类,子类属于父类。这是编码示例。

class Parent{
   String name
    static hasMany = [childs:Child] 
    static constraints = {
   }
}


class Child{
   String name
   static belongsTo = [parent:Parent]
   static constraints={}
}

问题是,一旦我得到父对象,与父类关联的子对象也被获取。但是当我将对象转换为 JSON 时,我并没有完全看到子对象,我只能看到子对象的 ID。我想查看子对象的所有列,而不仅仅是 Id。

转换后的 JSON 响应:

[{"class":"project.Parent","id":1,
  "name":"name1","childs":[{"class":"Child","id":1},{"class":"Review","id":2}]}]

但我也想要包含子对象名称的响应,如下

[{"class":"project.Parent","id":1,"name":"name1",
  "childs":[{"class":"Child","id":1,"name":"childname1"},
            {"class":"Review","id":2,"name":"childname2"}
           ]
}]

非常感谢任何帮助。提前致谢。

4

4 回答 4

57

问题在于使用默认 JSON 转换器。以下是您的选择:

 1. Default  -  all fields, shallow associations
    a. render blah as JSON

 2. Global deep converter - change all JSON converters to use deep association traversal
    a. grails.converters.json.default.deep = true

 3. Named config marshaller using provided or custom converters
    a. JSON.createNamedConfig('deep'){
        it.registerObjectMarshaller( new DeepDomainClassMarshaller(...) )
    }
    b. JSON.use('deep'){
        render blah as JSON
    }

 4. Custom Class specific closure marshaller 
    a. JSON.registerObjectMarshaller(MyClass){ return map of properties}
    b. render myClassInstance as JSON

 5. Custom controller based closure to generate a map of properties
    a. convert(object){
        return map of properties
    }
    b. render convert(blah) as JSON

您当前使用的是默认选项 1。

最简单的方法是使用选项 2 设置全局深度转换器,但请注意这会影响应用程序中的所有域类。这意味着,如果您有一个大型关联树最终形成一个顶级对象,并且您尝试转换这些顶级对象的列表,那么深度转换器将执行所有查询以获取所有关联对象及其关联对象转动。-您可以一次性加载整个数据库:) 小心。

于 2013-10-02T18:41:39.717 回答
3

最新的 grails 会自动进行深度转换,但您可能是延迟加载的受害者。

子项在访问时未加载,因此 JSON 转换器无法将它们转换为 JSON。解决方法是把这个

静态映射 = {孩子懒惰:假}

于 2014-09-27T09:09:21.820 回答
1

用户 dbrin 是正确的,但还有一个选择。您还可以使用 Grails GSON 插件:

https://github.com/robfletcher/grails-gson#readme

该插件在处理 json 数据时添加了更多功能。

于 2013-10-03T07:55:26.003 回答
1

建议的解决方案有效,但是我在引用“grailsApplication”时遇到了一些麻烦。事实证明,您可以像任何其他服务一样摄取它。我将以下代码放入

BootStrap.groovy

文件。此外,DeepDomainClassMarshaller类可以很好地处理双向循环引用,但要注意 JSON 有效负载在深度分离之后不会太大。

package aisnhwr

import grails.converters.JSON
import grails.core.GrailsApplication
import org.grails.web.converters.marshaller.json.DeepDomainClassMarshaller

class BootStrap {

    GrailsApplication grailsApplication

    def init = { servletContext ->
        JSON.createNamedConfig('deep'){
            it.registerObjectMarshaller( new DeepDomainClassMarshaller(false, grailsApplication) )
        }
    }
    def destroy = {
    }
}
于 2018-07-25T13:47:43.650 回答