Rendering JSON In Grails. Part 1: Collections, Testing and the JSONBuilder

One of the many useful features Grails provides is the ability to quickly render data as JSON so it’s possible to interface with the many AJAX libraries available with a minimum of coding fuss, or provide an API to 3rd parties with very little effort. Having implemented such behaviour I’ve found that a little more than the basic understanding is helpful for success in real applications, so over the next 3 posts I will attempt to convey the simplicity and power of this feature while also giving some practical tips.

In this first instalment I’ll cover simple rendering of Grails maps, lists and primitive data and also touch on the JSON builder.

My second post will look at plain old Groovy objects (POGOs) and how rendering of GORM domain objects may not be as straightforward as one might expect.

The final post will demonstrate how to extend the default rendering behaviour to overcome some of its side-effects by creating custom JSON object marshallers.

Rendering Grails Collections as JSON

Converting basic Grails collections to JSON using a controller’s render method is quite simple and may be all you ever need to know. Lists and maps are the easiest way to produce JSON mark up:

import grails.converters.JSON

class PersonController {
    def jsonPeople = {
        def myHomeAddress = [
                building:"25",
                street: "High Street",
                city:"Cambridge",
                country:"UK",
                pref: true] 

        def myWorkAddress = [
                building:"1",
                street: "Science Park",
                city:"Cambridge",
                country:"UK"]

        def dave = [
                name: "David Bower",
                address: [myHomeAddress, myWorkAddress]]

        def people = [people:[dave]]
        render people as JSON
    }
}

The resulting JSON is:

{
    "people": [
        {
            "name": "David Bower",
            "address": [
                {
                    "building": "25",
                    "street": "High Street",
                    "city": "Cambridge",
                    "country": "UK",
                    "pref": true
                },
                {
                    "building": "1",
                    "street": "Science Park",
                    "city": "Cambridge",
                    "country": "UK"
                }
            ]
        }
    ]
}

Each Grails map becomes a JSON object and Grails lists become JSON arrays. It’s exactly what you would hope for and is the method I come back to using time and again.

Unit Testing JSON Responses

The same package that provides JSON encoding also provides parsing, which is ideal for unit tests:

import grails.test.ControllerUnitTestCase
import grails.converters.JSON

class PersonControllerTests extends ControllerUnitTestCase {

  void testJsonResponse() {
      //Run the closure
      controller.jsonPeople()

      //parse the JSON
      def controllerResponse = controller.response.contentAsString
      def jsonResult = JSON.parse(controllerResponse)

      //navigate the JSON as an object
      assertNotNull "Missing people", jsonResult.people
      assertEquals "David Bower", jsonResult.people[0].name

  }
}

The result of the parse is a Groovy object that you can navigate.

Using the JSONBuilder

In addition to rendering maps and lists, it’s also possible to use the JSONBuilder to create custom JSON:

class PersonController {
    def jsonPeople = {
        render(contentType: "text/json") {
            people = [
                    {
                        name = "David Bower"
                        address = [
                                {
                                    building = "25"
                                    street = "High Street"
                                    city = "Cambridge"
                                    country = "UK"
                                    pref = true
                                },
                                {
                                    building = "1"
                                    street = "Science Park"
                                    city = "Cambridge"
                                    country = "UK"
                                }
                        ]
                    }
            ]
        }

    }
}

The JSON rendered is identical to the first example above.

I never use the builder in my own code, I’m yet to find an occasion where it would make the code clearer, less error prone or more reusable.

Next Time

Having seen how easy it is to render simple collections and test them, I’ll talk about rendering POGOs and GORM domain objects and some of the potential problems in my next post.

Further reading:
Advertisement

10 thoughts on “Rendering JSON In Grails. Part 1: Collections, Testing and the JSONBuilder

  1. Hi Dave,
    Thanks for the JSON write-ups; great stuff. Your approach to unit testing your JSON output was very helpful, as I was looking for a way to simple validate that controller.response was in fact a legit JSON object. I think parsing the content is much more elegant than searching for a MIME-Type header that doesn’t exist in the MockHTTpServletResponse 😉

  2. Hi Dave,
    Thanks a lot for this post. Grails docs are really very out of date lately (or very scattered). I have been searching for a long time on how to use the JSONBuilder to create more complex JSON objects.

    I had even given up last week and wrote my own builder, but doing some more search on Google today I found your post and it’s a relief to find out that I can rely on a Grails library to do such task.

  3. Good post,

    but did try the Controller unit test case with the json builder?

    My experience was that the rendering by the json builder would fail during the tests. Render Map as JSON does work however.

  4. Pingback: JSON and Grails | FOR PRIVATE PURPOSE ONLY
  5. // my PersonController

    def json(Long id){
    Person k = Person.get(id)
    def map =[name:k.getName(), b: k.vorname]
    render map as JSON
    }

  6. I have a simple question . Doesn’t JSONBuilder behave like MarkupBuilder ? With markupbuilder I can mass its reference to my calling functions and then can create xml stuff there and return. With JSONBuilder I am unable to do that.
    JSONBuilder jSON = new JSONBuilder()
    jSON.build{
    users = array{
    for(user in Users.list().sort({it.id})){
    person = {
    id = user.personName
    info = personInfo(user,jSON)
    }
    }
    } }

    So in person Info I have some stuff that I would like to build . Is it possible to do that ?

    Thanks
    Arvind

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s