我有两个域类,一个是父类,另一个是子类,我们之间有一个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"}
]
}]
任何帮助非常感谢。 提前谢谢。
答案 0 :(得分:53)
问题在于使用默认的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设置全局深度转换器,但要注意这会影响应用中的所有域类。这意味着如果你有一个大的关联树,最终在顶级对象中,并且你试图转换那些顶级对象的列表,则深度转换器将执行所有查询以获取所有关联对象及其关联对象。转。 - 你可以一次加载整个数据库 :)小心。
答案 1 :(得分:3)
最新的grails会自动深度转换,但你可能是延迟加载的受害者。
在访问时未加载子级,因此JSON转换器无法将它们转换为JSON。 解决方法是把这个
静态映射= {childs lazy:false}
答案 2 :(得分:1)
用户dbrin是正确的,但还有一个选项。您也可以使用Grails GSON插件:
https://github.com/robfletcher/grails-gson#readme
插件在处理json数据时增加了一些功能。
答案 3 :(得分:0)
建议的解决方案正在工作,但是在引用“ 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 = {
}
}