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:- Official Grails documentation – “XML and JSON Responses”: http://grails.org/doc/latest/guide/6.%20The%20Web%20Layer.html#6.1.7%20XML%20and%20JSON%20Responses
- Official Grails documentation – “More on JSONBuilder”: http://grails.org/doc/latest/guide/6.%20The%20Web%20Layer.html#6.1.8%20More%20on%20JSONBuilder
- Official Grails documentation – “Converters Reference”: http://grails.org/Converters+Reference
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 😉
Thanks Steve. I found more on the JSON parser recently (sometimes the Grails docs only seem to be available from Google!) – http://grails.org/Converters+Reference is worth a read if you haven’t seen it already, the converter configuration options are particularly helpful.
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.
Thanks Henrique, I’m glad it helped!
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.
nice!
// my PersonController
def json(Long id){
Person k = Person.get(id)
def map =[name:k.getName(), b: k.vorname]
render map as JSON
}
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
Nice article, the links in “Further reading” seem to be broken though.