JSON marshalling with Grails

Grails framework provides a convenient way to serialize GORM domain objects or simple beans to JSON using the converters. You can check its very clear and helpful documentation here. Default serialization is great but not sufficient sometimes when you have to deal with deep object graphs corresponding to One-To-Many relationships into your model. Fortunately, Grails provides a mean to override default serialization using the JSONBuilder. However, I did not found the documentation on JSONBuidler as clear as the one on converters… So this blog post is for recording and sharing some of the cases I came through and the associated code samples.

Marshalling of a One-To-One relationship

One of my use case was to serialiaze objects having a One-To-One relationship with another. Default behaviour of converter does not suit my need because it only rendered the id field of the associated entity (that because Grails identifiy the relationship as possibly lazily loaded and that the converter only serialize the foreign key: the id attribute). What I which was to render only some of the attributes that were helpful on the associated entity.

After some tries, I succeed using this piece of code :

withFormat {
   json {
      render(contentType:"text/json") {
         array{
            for (e in eventList){
               event id:e.id, dateCreated:e.dateCreated, entityId:e.entityId, type:e.type,
                  person:[id:e.person.id, username:e.person.username, userRealName:e.person.userRealName, avatarUrl:e.person.avatarUrl],
                  trail:[id:e.trail.id, name:e.trail.name]
            }
         }
      }
   }
}

Note that in that case for marshalling trail for example, you just have to return a map of the attributes you want to render. Also, for performance concern, be sure to have loaded your relationship eagerly using a fetch directive on your finder for example.

Another thing to notice is the usage of array{} directive in order here to render a List of Event objects.

Marshalling of a One-To-Many relationship

An extension of this use case was to realize the same thing (rendering of only some attributes) where my domain object has One-To-Many relationships. Thus I apply the same principle here combined with the use of the collect{} closure available in Groovy on List class.

withFormat {
   json {
      render(contentType:"text/json") {
         array{
            for (t in trails){
               trail id:t.id, name:t.name, description:t.description,
                  isRoundtrip:t.isRoundtrip, latitude:t.latitude, longitude:t.longitude,
                  categories:t.categories.collect{ return [id:it.id, name:it.name] }
            }
         }
      }
   }
}

Note again the usage of array{} directive because I wantend to marshall a list of Trail objects.

The categories One-to-Many association is here rendered using only its it and name attributes. This is relaized by the collect closure that return a map of attributes for each elements of the associtation.

Also for performance concern, be sure to load eagerly the associated objects in order to avoid the famous N+1 problem !

Let me know if this samples have helped you in any way ! Samples are working great on the Trailplans application for some weeks now !


Leave a comment