9.1.6 Customizing Response Rendering 2.4.4

See the light - agile, industrial strength, rapid web application development made easy

(Quick Reference) # 9.1.6 Customizing Response Rendering - Reference Documentation Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari Version: 2.4.4 ## Table of Contents ## 9.1.6 Customizing Response Rendering There are several ways to customize response rendering in Grails. ## 9.1.6.1 Customizing the Default Renderers The default renderers for XML and JSON can be found in the `grails.rest.render.xml` and `grails.rest.render.json` packages respectively. These use the Grails converters (`grails.converters.XML` and `grails.converters.JSON`) by default for response rendering. You can easily customize response rendering using these default renderers. A common change you may want to make is to include or exclude certain properties from rendering. #### Including or Excluding Properties from Rendering As mentioned previously, Grails maintains a registry of `grails.rest.render.Renderer` instances. There are some default configured renderers and the ability to register or override renderers for a given domain class or even for a collection of domain classes. To include a particular property from rendering you need to register a custom renderer by defining a bean in `grails-app/conf/spring/resources.groovy`:

    import grails.rest.render.xml.*beans = {
        bookRenderer(XmlRenderer, Book) {
            includes = ['title']
        }
    }
The bean name is not important (Grails will scan the application context for all registered renderer beans), but for organizational and readability purposes it is recommended you name it something meaningful. To exclude a property, the `excludes` property of the `XmlRenderer` class can be used:

    import grails.rest.render.xml.*beans = {
        bookRenderer(XmlRenderer, Book) {
            excludes = ['isbn']
        }
    }
#### Customizing the Converters As mentioned previously, the default renders use the `grails.converters` package under the covers. In other words, under the covers they essentially do the following:

    import grails.converters.*…
    render book as XML// or render book as JSON
Why the separation between converters and renderers? Well a renderer has more flexibility to use whatever rendering technology you chose. When implementing a custom renderer you could use Jackson, Gson or any Java library to implement the renderer. Converters on the other hand are very much tied to Grails' own marshalling implementation. ## 9.1.6.2 Registering Custom Objects Marshallers Grails' Converters feature the notion of an ObjectMarshaller and each type can have a registered `ObjectMarshaller`. You can register custom `ObjectMarshaller` instances to completely customize response rendering. For example, you can define the following in `BootStrap.init`:
    XML.registerObjectMarshaller Book, { Book book, XML xml ->
      xml.attribute 'id', book.id
      xml.build {
        title(book.title)
      }
    }
You can customize the formatting of an individual value this way too. For example the JodaTime plugin does the following to support rendering of JodaTime dates in JSON output:
    JSON.registerObjectMarshaller(DateTime) {
        return it?.toString("yyyy-MM-dd'T'HH:mm:ss'Z'")
    }
In the case of JSON it's often simple to use a map to customize output:
    JSON.registerObjectMarshaller(Book) {
      def map= [:]
      map['titl'] = it.title
      map['auth'] = it.author
      return map
    }
#### Registering Custom Marshallers via Spring Note that if you have many custom marshallers it is recommended you split the registration of these into a separate class:

    class CustomMarshallerRegistrar {    @javax.annotation.PostConstruct
        void registerMarshallers() {
            JSON.registerObjectMarshaller(DateTime) {
                return it?.toString("yyyy-MM-dd'T'HH:mm:ss'Z'")
            }
        }
    }
Then define this class as Spring bean in `grails-app/conf/spring/resources.groovy`:
    beans = {
        myCustomMarshallerRegistrar(CustomMarshallerRegistrar)
    }
The `PostConstruct` annotation will get triggered on startup of your application. ## 9.1.6.3 Using Named Configurations for Object Marshallers It is also possible to register named configurations. For example:
    XML.createNamedConfig('publicApi') {
      it.registerObjectMarshaller(Book) { Book book, XML xml ->
        // do public API
      }
    }
    XML.createNamedConfig('adminApi') {
      it.registerObjectMarshaller(Book) { Book book, XML xml ->
        // do admin API
      }
    }
Then when you use either the `render` or `respond` methods you can wrap the call in a named configuration if necessary to customize rendering per request:
    XML.use( isAdmin ? 'adminApi' : 'publicApi') {
        render book as XML
    }
or
    XML.use( isAdmin ? 'adminApi' : 'publicApi') {
        respond book
    }
## 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()
      }
    }
## 9.1.6.5 Implementing a Custom Renderer If you want even more control of the rendering or prefer to use your own marshalling techniques then you can implement your own `Renderer` instance. For example below is a simple implementation that customizes the rendering of the `Book` class:

    package myapp
    import grails.rest.render.*
    import org.codehaus.groovy.grails.web.mime.MimeTypeclass BookXmlRenderer extends AbstractRenderer<Book> {
        BookXmlRenderer() {
            super(Book, [MimeType.XML,MimeType.TEXT_XML] as MimeType[])
        }    void render(Book object, RenderContext context) {
            context.contentType = MimeType.XML.name        def xml = new groovy.xml.MarkupBuilder(context.writer)
            xml.book(id: object.id, title:object.title)
        }
    }
The `AbstractRenderer` super class has a constructor that takes the class that it renders and the `MimeType`(s) that are accepted (via the ACCEPT header or file extension) for the renderer. To configure this renderer, simply add it is a bean to `grails-app/conf/spring/resources.groovy`:
    beans = {
        bookRenderer(myapp.BookXmlRenderer)
    }
The result will be that all `Book` instances will be rendered in the following format:
    <book id="1" title="The Stand"/>
Note that if you change the rendering to a completely different format like the above, then you also need to change the binding if you plan to support POST and PUT requests. Grails will not automatically know how to bind data from a custom XML format to a domain class otherwise. See the section on "Customizing Binding of Resources" for further information. #### Container Renderers A `grails.rest.render.ContainerRenderer` is a renderer that renders responses for containers of objects (lists, maps, collections etc.). The interface is largely the same as the `Renderer` interface except for the addition of the `getComponentType()` method, which should return the "contained" type. For example:
    class BookListRenderer implements ContainerRenderer<List, Book> {
        Class<List> getTargetType() { List }
        Class<Book> getComponentType() { Book }
        MimeType[] getMimeTypes() { [ MimeType.XML] as MimeType[] }
        void render(List object, RenderContext context) {
            ....
        }
    }
## 9.1.6.6 Using GSP to Customize Rendering You can also customize rendering on a per action basis using Groovy Server Pages (GSP). For example given the `show` action mentioned previously:
    def show(Book book) {
        respond book
    }
You could supply a `show.xml.gsp` file to customize the rendering of the XML:
    <%@page contentType="application/xml"%>
    <book id="${book.id}" title="${book.title}"/>
| Quick Reference (hide)