Source

JSONExclusionMarshaller / JSONExclusionMarshallerGrailsPlugin.groovy

Full commit
class JSONExclusionMarshallerGrailsPlugin {
    // the plugin version
    def version = "0.2"
    // the version or versions of Grails the plugin is designed for
    def grailsVersion = "2.2 > *"
    // resources that are excluded from plugin packaging
    def pluginExcludes = [
        "grails-app/views/error.gsp"
    ]

    // TODO Fill in these fields
    def title = "JSON Exclusion Marshaller Plugin" // Headline display name of the plugin
    def author = "Jason Stonebraker"
    def authorEmail = "jasonstonebraker@gmail.com"
    def description = '''\
A Grails plugin that adds a convenience method to the Grails JSON converter for excluding properties from JSON output. Example use: excludeForPublicAPI(MyDomainClass, ['id', 'class']).
'''

    // URL to the plugin's documentation
    def documentation = "http://grails.org/plugin/json-exclusion-marshaller"

    // Extra (optional) plugin metadata

    // License: one of 'APACHE', 'GPL2', 'GPL3'
//    def license = "APACHE"

    // Details of company behind the plugin (if there is one)
//    def organization = [ name: "My Company", url: "http://www.my-company.com/" ]

    // Any additional developers beyond the author specified above.
//    def developers = [ [ name: "Joe Bloggs", email: "joe@bloggs.net" ]]

    // Location of the plugin's issue tracker.
   def issueManagement = [ system: "Bitbucket", url: "https://bitbucket.org/stonebraker/jsonexclusionmarshaller/issues" ]

    // Online location of the plugin's browseable source code.
   def scm = [ url: "https://bitbucket.org/stonebraker/jsonexclusionmarshaller/src" ]

    def doWithWebDescriptor = { xml ->
        // TODO Implement additions to web.xml (optional), this event occurs before
    }

    def doWithSpring = {
        // TODO Implement runtime spring config (optional)
    }

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

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

            if (isAnExclusionaryMethod) {
                def impl = { Object[] vargs ->
                    def 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
                                gdc = new org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass(type),
                                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
                        }
                    }
                }

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

                return impl(args)
            } else {
                throw new MissingMethodException(name, grails.converters.JSON.class, args)
            }
        }

    }

    def doWithApplicationContext = { applicationContext ->
        // TODO Implement post initialization spring config (optional)
    }

    def onChange = { event ->
        // TODO Implement code that is executed when any artefact that this plugin is
        // watching is modified and reloaded. The event contains: event.source,
        // event.application, event.manager, event.ctx, and event.plugin.
    }

    def onConfigChange = { event ->
        // TODO Implement code that is executed when the project configuration changes.
        // The event is the same as for 'onChange'.
    }

    def onShutdown = { event ->
        // TODO Implement code that is executed when the application shuts down (optional)
    }
}