Archive

Posts Tagged ‘metamethod’

Grails easy JSON DTO’s

May 25th, 2013 No comments

Some JSON is only used in specific places. For these occurrences I use extension methods / meta methods to easily convert my classes into the required JSON without the need for a specific mapping/dto class. To do this I declare a Markup interface (called Mappable) on which the method can be invoked.

I put the following interface in src/groovy:

package com.example.json
 
/**
 * Markup interface so we can add extension methods to convert objects to maps.
 * @see MetaMethods.groovy
 */
interface Mappable {}

I then add the following to my MetaMethods class in src/groovy:

package com.example.json;
 
class MetaMethods {
    static void register() {
        Mappable.metaClass.toMap { whitelist, blacklist ->
            /* metaClass, class */
            def map = [:];
 
            /* id seems to be a special case */
            if (("id" in whitelist) || (!"id" in blacklist)) {
                map["id"] = delegate["id"];
            }
 
            if (whitelist) {
                whitelist.each {
                    map[it] = delegate[it]
                }
            } else if (blacklist) {
                delegate.properties.each { prop, val ->
                    if (!(prop in blacklist)) {
                        map[prop] = val;
                    }
                }
            }
            return map;
        }
    }
}

I register the metamethods in my Bootstrap.groovy

class BootStrap {
    def init = { servletContext ->
 
        /* Register our own Meta Methods/Extension Methods */
        MetaMethods.register();
    }
}

Now we can create easy JSON dto’s based on our domain (don’t forget to add the Mappable interface to your domain classes).

Usage example:

        def jsonMap = myDomainClass.toMap(["id", "propertyX", "propertyZ"], []); // 1st level properties
        jsonMap["customer"] = myDomainClass.customer ? myDomainClass.customer.toMap(["id", "fullName", "firstName", "insertion", "lastName"], []) : null; // 2nd level properties
        render jsonMap as JSON; // or as XML

Happy Grailing!