Чтобы преобразователь мог преобразовать всю структуру объекта, вам нужно установить свойство в конфигурации, чтобы указать, что в противном случае он будет просто включать идентификатор дочернего объекта, поэтому вам нужно добавить это:
grails.converters.json.default.deep = true
Для получения дополнительной информации перейдите по ссылке Справочник по преобразователям Grails .
Однако, как вы упомянули в комментарии выше, это все или ничего, поэтому вы можете создать своего собственного маршаллера для своего класса. Я должен был сделать это раньше, потому что мне нужно было включить некоторые очень специфические свойства, поэтому я создал класс, расширяющий org.codehaus.groovy.grails.web.converters.marshaller.json.DomainClassMarshaller. Что-то вроде:
class MyDomainClassJSONMarshaller extends DomainClassMarshaller {
public MyDomainClassJSONMarshaller() {
super(false)
}
@Override
public boolean supports(Object o) {
return (ConverterUtil.isDomainClass(o.getClass()) &&
(o instanceof MyDomain))
}
@Override
public void marshalObject(Object value, JSON json) throws ConverterException {
JSONWriter writer = json.getWriter();
Class clazz = value.getClass();
GrailsDomainClass domainClass = ConverterUtil.getDomainClass(clazz.getName());
BeanWrapper beanWrapper = new BeanWrapperImpl(value);
writer.object();
writer.key("class").value(domainClass.getClazz().getName());
GrailsDomainClassProperty id = domainClass.getIdentifier();
Object idValue = extractValue(value, id);
json.property("id", idValue);
GrailsDomainClassProperty[] properties = domainClass.getPersistentProperties();
for (GrailsDomainClassProperty property: properties) {
if (!DomainClassHelper.isTransient(transientProperties, property)) {
if (!property.isAssociation()) {
writer.key(property.getName());
// Write non-relation property
Object val = beanWrapper.getPropertyValue(property.getName());
json.convertAnother(val);
} else {
Object referenceObject = beanWrapper.getPropertyValue(property.getName());
if (referenceObject == null) {
writer.key(property.getName());
writer.value(null);
} else {
if (referenceObject instanceof AbstractPersistentCollection) {
if (isRenderDomainClassRelations(value)) {
writer.key(property.getName());
// Force initialisation and get a non-persistent Collection Type
AbstractPersistentCollection acol = (AbstractPersistentCollection) referenceObject;
acol.forceInitialization();
if (referenceObject instanceof SortedMap) {
referenceObject = new TreeMap((SortedMap) referenceObject);
} else if (referenceObject instanceof SortedSet) {
referenceObject = new TreeSet((SortedSet) referenceObject);
} else if (referenceObject instanceof Set) {
referenceObject = new HashSet((Set) referenceObject);
} else if (referenceObject instanceof Map) {
referenceObject = new HashMap((Map) referenceObject);
} else {
referenceObject = new ArrayList((Collection) referenceObject);
}
json.convertAnother(referenceObject);
}
} else {
writer.key(property.getName());
if (!Hibernate.isInitialized(referenceObject)) {
Hibernate.initialize(referenceObject);
}
json.convertAnother(referenceObject);
}
}
}
}
}
writer.endObject();
}
...
}
Этот код, приведенный выше, в значительной степени совпадает с кодом DomainClassMarshaller, идея заключается в том, чтобы добавить или удалить то, что вам нужно.
Тогда для того, чтобы Grails использовал этот новый конвертер, вам нужно зарегистрировать его в файле resources.groovy, например:
// Here we are regitering our own domain class JSON Marshaller for MyDomain class
myDomainClassJSONObjectMarshallerRegisterer(ObjectMarshallerRegisterer) {
converterClass = grails.converters.JSON.class
marshaller = {MyDomainClassJSONMarshaller myDomainClassJSONObjectMarshaller ->
// nothing to configure, just need the instance
}
priority = 10
}
Как вы можете видеть, этот маршаллер работает для определенного класса, поэтому, если вы хотите сделать более универсальный, вы можете создать супер класс и сделать так, чтобы ваши классы наследовали от него, так что в support method вы говорите, что этот маршаллер поддерживает все классы, которые являются экземплярами этого суперкласса.
Я предлагаю пересмотреть код grails для конвертеров, который даст вам представление о том, как они работают внутри, а затем о том, как вы можете расширить его, чтобы он работал так, как вам нужно.
Этот другой пост в Nabble тоже может помочь.
Кроме того, если вам нужно сделать это и для XML, вы просто расширяете класс org.codehaus.groovy.grails.web.converters.marshaller.xml.DomainClassMarshaller и выполняете тот же процесс, чтобы зарегистрировать его и т. Д.