Grails get child domain objects
The issue is with the use of default JSON converter. Here are your options:
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
You are currently using Option 1, which is default.
The simplest you can do is use Option 2 to set global deep converter, but be aware this effects ALL domain classes in your app. Which means that if you have a large tree of associations culminating in a top level object and you try to convert a list of those top level objects the deep converter will execute all of the queries to fetch all of the associated objects and their associated objects in turn. - You could load an entire database in one shot :) Be careful.
The latest grails automatically deep converts but you are probably a victim of lazy loading.
The children are not loaded at access and hence the JSON converter cannot convert them to JSON. The workaround is to put this
static mapping = { childs lazy: false }
user dbrin is correct, but there's one more option. You could also use the Grails GSON Plugin:
https://github.com/robfletcher/grails-gson#readme
The Plugin adds some more features when dealing with json data.
The suggested solution is working, however I had some trouble referencing "grailsApplication". It turns out, that you can ingest it like any other service. I put the following code into the
BootStrap.groovy
file. Also, the class DeepDomainClassMarshaller handles quite well bidirectional circular references, but beware that the JSON Payload is not to big after all deep deferencation.
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 = {
}
}