Last updated by jrobens 5 months ago
Be advised This doc was created for Grails versions lower than < 2.3.x There are many new features regarding Converters on 2.3.x

Grails Converters Reference

The Converters aim to give you the ability to quickly transform any kind of Java/Groovy Objects to JSON/XML

The Converter Classes

Currently, there are 4 classes that can be used as Converters:

  • for JSON Conversion
    • grails.converters.JSON
    • grails.converters.deep.JSON
  • for XML Conversion
    • grails.converters.XML
    • grails.converters.deep.XML
Note: This is outdated. The deep converters are deprecated and the normal converters deep-convert (Grails 1.3.7).

The default Converters (in the grails.converter package) render Domainclass associations as ID's, while the Deep Converters (JSON.use('deep')) also fully render the associations (nested domainclass instances) and also handle circular relations. The difference between those converters only affects how Domain Class instances are handled, all other types of objects are serialized similar.

To use the deep conversion, as opposed to the default conversion, you just have to say JSON that it should use deep conversion.

import grails.converters.JSON

… JSON.use('deep') render someObject as JSON

Initializing a Converter

To create a converter instance you have to choose from one the following notations:

default initialization

def converter = new JSON(target: Book.list());
Constructs a new instance of the JSON Converter and sets the target property to the object which should get converted.

the "as" operator

def converter = Book.list() as JSON
Same as the example above using a neat syntax.

Using a Converter Instance

What can you do, when you have successfully created a converter instance?

toString()

Calling toString on a Converter instance performs the conversion of the target and constructs a String containing the resulting JSON/XML.

def converter = Book.get(1) as JSON;
println converter.toString();

rendering to a java.io.Writer
The render method of Converters can take any java.io.Writer

def converter = Book.list() as XML
converter.render(new java.io.FileWriter("/path/to/my/file.xml"));

rendering to a HttpServletResponse
You can use a Converter to render the result directly to a HttpServletResponse. The Converter will also set the appropriate Content-Type Header. The following example illustrated two ways to achieve that:

import grails.converters.*;

class AjaxController {

def list1 = { def converter = Book.list() as JSON converter.render(response) // Calling the Converter's render method directly return false }

def list2 = { render Book.list() as JSON // Using the Controller's dynamic render method }

def xmllist = { render Book.list as XML }

}

Codecs

The Converters plugin also provides codecs (as described in the User Guide) to quickly convert arbitary objects to JSON/XML without the need to import a Converter class.

encodeAsJSON
String result = someObject.encodeAsJSON();

encodeAsXML
String result = someObject.encodeAsXML();

Reverse Conversion

Both Converters are featuring 3 different static parse methods.

API Documentation:

parse(String)
import grails.converters.*
import org.codehaus.groovy.grails.web.json.*; // package containing JSONObject, JSONArray,...

def o = JSON.parse("{ foo: 'bar' }"); // Parse a JSON String assert o instanceof JSONObject // In this case, JSON.parse returns a JSONObject instance assert o instanceof Map // which implements the Map interface assert o.foo == 'bar' // access a property

// Parse another JSON String containing a Javascript Array def a = JSON.parse("[ 1, 2, 3]") assert a instanceof JSONArray assert a instanceof List assert a[0] == 1

// The following works in Grails >= 1.0.5 def rootNode = XML.parse """<foo><bar ding="dong"></foo>""" // Same as Groovy's XmlSlurper.parseText(String) assert rootNode instanceof groovy.util.slurpersupport.GPathResult assert rootNode.bar.@ding == 'dong'

parse(InputStream, String)
Both Converters feature a static method for parsing the content from an java.io.InputStream. The second parameter of this method is the character encoding to use.
import grails.converters.*

def json = JSON.parse(new FileInputStream("/path/to/file.json"), "UTF-8") def xml = XML.parse(new FileInputStream("/path/to/file.xml"), "UTF-8")

parse(HttpServletRequest)
A convenience method which checks the Request Content-Type, tries to detect the character encoding of the request and then parses the Request Body using the request's inputStream.

request.XML and request.JSON
When you access request.XML or request.JSON the appropriate Converters' parse method is automatically invoked which then checks the Content-Type header of the Request and in the case of a match parses the Request Body
import grails.converters.*

class SomeController { // We assume the client requests this action using the request Content-Type // "application/json" and { foo: 'bar' } as Request Body def postJson = { def json = request.JSON assert json.foo == 'bar' } // We assume the client requests this action using the request Content-Type // "text/xml" and <foo><bar ding="dong"></foo> as Request Body def postXml = { def xml = request.XML assert xml.bar.@ding == 'dong' } }

Configuration Options (Since 1.1)

  • grails.converters.encoding (String) - Set the default output encoding for the Converters ( default: "UTF-8" )
  • grails.converters.default.circular.reference.behaviour (String) - Configure the behaviour of the Converters when a circular reference is detected. This can be:
    • "DEFAULT" (Insert a reference to the circular referenced object)
    • "INSERT_NULL" (Renders null instead of the referenced object)
    • "EXCEPTION" (Throw an exception in that case). ( default: "DEFAULT" )
  • grails.converters.xml.circular.reference.behaviour (String) - Circular reference behaviour only for the XML Converter
  • grails.converters.json.circular.reference.behaviour (String) - Circular reference behaviour only for the JSON Converter
  • grails.converters.default.pretty.print (Boolean) - Whether the default output of the Converters is pretty-printed ( default: false )
  • grails.converters.xml.pretty.print (Boolean) - Whether the output of the XML Converter is pretty-printed
  • grails.converters.json.pretty.print (Boolean) - Whether the output of the JSON Converter is pretty-printed
  • grails.converters.json.default.deep (Boolean) - Set to true if the grails.converters.JSON Converter should default to deeply serializing Domainclass relations (default: false)
  • grails.converters.xml.default.deep (Boolean) - Set to true if the grails.converters.XML Converter should default to deeply serializing Domainclass relations (default: false)
  • grails.converters.json.date (String) - Configure how Date values are serialized to JSON
    • "default" - String representation according to the JSON specification
    • "javascript" - new Date(...)
  • grails.converters.domain.include.version (Boolean) - Set to true if both XML and JSON Converters should default include version from domain (default: false)
  • grails.converters.xml.domain.include.version (Boolean) - Set to true if XML Converter should default include version from domain (default: false)
  • grails.converters.json.domain.include.version (Boolean) - Set to true if JSON Converter should default include version from domain (default: false)
Example configuration (in grails-app/conf/Config.groovy)
grails.converters {
    encoding = "ISO-8859-1"
    json.date = "javascript"
    default.pretty.print = true
}

Customizing Converters Results

You can specify which are the properties of a class that should be included in the JSON representation by registering a specific Object Marshaller(grails.converters.JSON.registerObjectMarshaller) :

// a class to output in JSON

class User { String login String passwd

// JSON definition of the User object static { grails.converters.JSON.registerObjectMarshaller(User) { // you can filter here the key-value pairs to output: return it.properties.findAll {k,v -> k != 'passwd'} }

}

// a controller action def myAction() { def a = new User(login:'bob', passwd:'1234') def list = [a, a] render list as JSON }