1. Jason Stonebraker
  2. JSONExclusionMarshaller

Source

JSONExclusionMarshaller / JsonExclusionMarshallerGrailsPlugin.groovy

import grails.converters.JSON
import org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass

class JsonExclusionMarshallerGrailsPlugin {
    def version = "0.2"
    def grailsVersion = "2.0 > *"
    def pluginExcludes = [
        "grails-app/domain/**"
    ]

    def title = "JSON Exclusion Marshaller Plugin"
    def author = "Jason Stonebraker"
    def authorEmail = "jasonstonebraker@gmail.com"
    def description = '''Adds a convenience method to the Grails JSON converter for excluding properties from JSON output. Example use: excludeForPublicAPI(MyDomainClass, ['id', 'class']).'''

    def documentation = "http://grails.org/plugin/json-exclusion-marshaller"

    def license = "APACHE"
    def issueManagement = [ system: "Bitbucket", url: "https://bitbucket.org/stonebraker/jsonexclusionmarshaller/issues" ]
    def scm = [ url: "https://bitbucket.org/stonebraker/jsonexclusionmarshaller/src" ]

    def doWithDynamicMethods = { ctx ->
        // TODO Implement registering dynamic methods to classes (optional)
        // println "Do with dynamic methods called..."

        JSON.metaClass.static.methodMissing = { String name, args ->
            def jsonConverter = delegate
            boolean isAnExclusionaryMethod = name.startsWith('excludeFor')

            if (!isAnExclusionaryMethod) {
                throw new MissingMethodException(name, JSON, args)
            }

            def impl = { Object[] vargs ->
                String configName = name // The name of the missing method called
                def type = vargs[0]
                def propertiesToExclude = vargs[1]

                jsonConverter.createNamedConfig(configName) {
                    it.registerObjectMarshaller(type) {
                        def obj = it // Object being marshalled
                        def gdc = new DefaultGrailsDomainClass(type)
                        def map = [:]

                        map["${gdc.identifier.name}"] = obj."${gdc.identifier.name}"
                        map['class'] = obj.getClass().name

                        gdc.persistentProperties.each { property ->
                            map["${property.name}"] = obj."${property.name}"
                        }

                        propertiesToExclude.each { property -> map.remove(property) }

                        return map
                    }
                }
            }

            JSON.metaClass."$name" = impl //future calls will use this

            return impl(args)
        }
    }
}