(Quick Reference)

9.1.6.4 Implementing the ObjectMarshaller Interface - Reference Documentation

Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari

Version: 3.0.12

9.1.6.4 Implementing the ObjectMarshaller Interface

For more complex marshallers it is recommended you implement the ObjectMarshaller interface. For example given a domain class:

class Book {
    String title
}

By default the output when using:

render book as XML

Would look like:

<book id="1">
   <title>The Stand</title>
</book>

To write a custom marshaller you can do the following:

class BookMarshaller implements ObjectMarshaller<XML> {

public boolean supports(Object object) { return object instanceof Book }

public void marshalObject(Object object, XML converter) { Book book = (Book)object converter.chars book.title } }

And then register the marshaller with:

XML.registerObjectMarshaller(new BookMarshaller())

With the custom ObjectMarshaller in place, the output is now:

<book>The Stand</book>

Customizing the Name of the Root Element

If you wish the customize the name of the surrounding element, you can implement NameAwareMarshaller:

class BookMarshaller implements ObjectMarshaller<XML>,NameAwareMarshaller {

...

String getElementName(Object o) { return 'custom-book' }

}

With the above change the output would now be:

<custom-book>The Stand</custom-book>

Outputting Markup Using the Converters API or Builder

With the passed Converter object you can explicitly code to the Converters API to stream markup to the response:

public void marshalObject(Object object, XML converter) {
  Book book = (Book)object

converter.attribute 'id', book.id.toString() converter.attribute 'date-released', book.dateReleased.toString()

converter.startNode 'title' converter.chars book.title converter.end()

}

The above code results in:

<book id="1" date-released="...">
   <title>The Stand</title>
</book>

You can also use a builder notation to achieve a similar result (although the builder notation does not work for CompileStatic):

public void marshalObject(Object object, XML converter) {
  Book b = (Book)object

converter.build { book(id: b.id) { title b.title } } }

Using the convertAnother Method to Recursively Convert Objects

To create more complex responses you can use the convertAnother method to convert associations and other objects:

public void marshalObject(Object object, XML converter) {
  Book book = (Book)object

converter.startNode 'title' converter.chars book.title converter.end()

if (book.authors) { converter.startNode 'authors' for(author in book.authors) { converter.convertAnother author } converter.end() } }