in grails-views-gson/src/main/groovy/grails/plugin/json/view/api/internal/DefaultGrailsJsonViewHelper.groovy [505:673]
protected void process(StreamingJsonBuilder.StreamingJsonDelegate jsonDelegate, PersistentEntity entity, Object object, Map<Object, JsonOutput.JsonWritable> processedObjects, List<String> incs, List<String> excs, String path, boolean isDeep, boolean renderNulls, List<String> expandProperties = [], boolean includeAssociations = true, Closure customizer = null) {
ResolvableGroovyTemplateEngine templateEngine = view.templateEngine
Locale locale = view.locale
renderEntityId(jsonDelegate, processedObjects, incs, excs, path, isDeep, renderNulls, expandProperties, getValidIdProperties(entity, object, incs, excs, path))
for (prop in entity.persistentProperties) {
def propertyName = prop.name
String qualified = "${path}${propertyName}"
if (!includeExcludeSupport.shouldInclude(incs, excs, qualified)) {
continue
}
def value = ((GroovyObject) object).getProperty(propertyName)
if(value == null) {
if (renderNulls) {
jsonDelegate.call(propertyName, NULL_OUTPUT)
}
continue
}
if (!(prop instanceof Association)) {
processSimpleProperty(jsonDelegate, (PersistentProperty) prop, propertyName, value)
} else if(includeAssociations) {
Association ass = (Association) prop
def associatedEntity = ass.associatedEntity
if (ass instanceof Embedded) {
def propertyType = ass.type
def template = renderTemplate(value, propertyType)
if(template != null) {
jsonDelegate.call(propertyName, template)
}
else {
jsonDelegate.call(propertyName) {
StreamingJsonBuilder.StreamingJsonDelegate embeddedDelegate = (StreamingJsonBuilder.StreamingJsonDelegate)getDelegate()
if(associatedEntity != null) {
process(embeddedDelegate, associatedEntity,value, processedObjects, incs, excs , "${qualified}.", isDeep, renderNulls)
}
else {
processSimple(embeddedDelegate, value, processedObjects, incs, excs, "${qualified}.", renderNulls)
}
}
}
}
else if(ass instanceof ToOne) {
if(associatedEntity != null) {
def propertyType = ass.type
if(!ass.circular && (isDeep || expandProperties.contains(qualified))) {
def childTemplate = templateEngine?.resolveTemplate(TemplateResolverUtils.shortTemplateNameForClass(propertyType), locale)
if(childTemplate != null && notCircular((JsonViewTemplate)childTemplate)) {
def model = [(GrailsNameUtils.getPropertyName(propertyType)): value]
def childView = prepareWritable(childTemplate, model)
def writer = new FastStringWriter()
childView.writeTo(writer)
jsonDelegate.call(propertyName, JsonOutput.unescaped(writer.toString()))
} else if (!ass.isOwningSide() && ass.isBidirectional() && !expandProperties.contains(qualified)) {
continue
}
else {
jsonDelegate.call(propertyName) {
StreamingJsonBuilder.StreamingJsonDelegate embeddedDelegate = (StreamingJsonBuilder.StreamingJsonDelegate)getDelegate()
process(embeddedDelegate, getPersistentEntity(associatedEntity, value), value, processedObjects, incs, excs , "${qualified}.", isDeep, renderNulls, expandProperties)
}
}
}
else {
Map validIdProperties = getValidIdProperties(associatedEntity, value, incs, excs, "${qualified}.")
if (validIdProperties.size() > 0) {
jsonDelegate.call(propertyName) {
renderEntityId(delegate, processedObjects, incs, excs, "${qualified}.", isDeep, renderNulls, expandProperties, validIdProperties)
}
}
}
}
}
else if((ass instanceof ToMany) && Iterable.isAssignableFrom(ass.type)) {
if(ass instanceof Basic) {
// basic collection types like lists of strings etc. just render directly
jsonDelegate.call(propertyName, value)
}
else {
boolean shouldExpand = expandProperties.contains(qualified)
if(!isDeep && !shouldExpand) {
def proxyHandler = ((JsonView) view).getProxyHandler()
if(proxyHandler?.isProxy(value) && !proxyHandler.isInitialized(value)) {
continue
}
if(value instanceof PersistentCollection) {
PersistentCollection pc = (PersistentCollection)value
if(!pc.isInitialized()) continue
}
}
if(isDeep || shouldExpand) {
def propertyType = ass.associatedEntity.javaClass
def childTemplate = templateEngine?.resolveTemplate(propertyType, locale)
if(childTemplate != null && notCircular((JsonViewTemplate)childTemplate)) {
def writer = new FastStringWriter()
def iterator = ((Iterable) value).iterator()
writer.write(JsonOutput.OPEN_BRACKET)
def childPropertyName = GrailsNameUtils.getPropertyName(propertyType)
while(iterator.hasNext()) {
def o = iterator.next()
def model = [(childPropertyName): o]
def childView = prepareWritable(childTemplate, model)
childView.writeTo(writer)
if(iterator.hasNext()) {
writer.write(JsonOutput.COMMA)
}
}
writer.write(JsonOutput.CLOSE_BRACKET)
jsonDelegate.call(propertyName, JsonOutput.unescaped(writer.toString()))
} else if (!ass.isOwningSide() && ass.isBidirectional() && !expandProperties.contains(qualified)) {
continue
} else {
jsonDelegate.call(propertyName, (Iterable)value) { child ->
StreamingJsonBuilder.StreamingJsonDelegate embeddedDelegate = (StreamingJsonBuilder.StreamingJsonDelegate)getDelegate()
process(embeddedDelegate, getPersistentEntity(associatedEntity, child), child, processedObjects, incs, excs , "${qualified}.", isDeep, renderNulls)
}
}
} else {
jsonDelegate.call(propertyName, (Iterable)value) { child ->
Map idProperties = getValidIdProperties(associatedEntity, child, incs, excs, "${qualified}.") as Map
if (idProperties.size() > 0) {
renderEntityId((StreamingJsonBuilder.StreamingJsonDelegate) getDelegate(), processedObjects, incs, excs, "${qualified}.", isDeep, renderNulls, expandProperties, idProperties)
} else {
StreamingJsonBuilder.StreamingJsonDelegate embeddedDelegate = (StreamingJsonBuilder.StreamingJsonDelegate)getDelegate()
process(embeddedDelegate, getPersistentEntity(associatedEntity, child), child, processedObjects, incs, excs , "${qualified}.", isDeep, renderNulls, expandProperties)
}
}
}
}
}
else if(ass instanceof EmbeddedCollection) {
if(Iterable.isAssignableFrom(ass.type) && associatedEntity != null) {
jsonDelegate.call(propertyName, (Iterable)value) { child ->
StreamingJsonBuilder.StreamingJsonDelegate embeddedDelegate = (StreamingJsonBuilder.StreamingJsonDelegate)getDelegate()
process(embeddedDelegate, getPersistentEntity(associatedEntity, child), child, processedObjects, incs, excs , "${qualified}.", isDeep, renderNulls, expandProperties)
}
}
} else if (ass instanceof Basic) {
jsonDelegate.call(propertyName, value)
}
}
}
if (customizer != null) {
customizer.setDelegate(jsonDelegate)
if (customizer.maximumNumberOfParameters == 1) {
customizer.call(object)
} else {
customizer.call()
}
}
}