开发者

grails.converters.JSON except few properties

I am using grails-1.3.2 and hbase-0.2.4开发者_开发问答.

I have the following domain class:

class MyClass{
  String val1
  String val2
  String val3

   //----

 }

class MyClassController{
    def someAction = {
        def myClass = new MyClass()
        //----

        String valAsJson = (myClass as JSON)

        render valAsJson 
     }
}

My question is, is any short way render only part of properties(for example render all except val3 property) ?


You can do something like this :

def myClass = MyClass.get(1)

 //include
 render myClass.part(include:['val1', 'val2']) as JSON

 //except
 render job.part(except:['val2','val3']) as JSON

Bootstrap.groovy :

import org.codehaus.groovy.grails.orm.hibernate.support.ClosureEventTriggeringInterceptor as Events

class BootStrap {
 def grailsApplication

 def excludedProps = [Events.ONLOAD_EVENT,
    Events.BEFORE_DELETE_EVENT, Events.AFTER_DELETE_EVENT,
    Events.BEFORE_INSERT_EVENT, Events.AFTER_INSERT_EVENT,
    Events.BEFORE_UPDATE_EVENT, Events.AFTER_UPDATE_EVENT]

  def init = { servletContext ->
     grailsApplication.domainClasses.each{ domainClass ->
         domainClass.metaClass.part= { m ->
             def map= [:]
             if(m.'include'){
                 m.'include'.each{
                     map[it]= delegate."${it}"
                 }
             }else if(m.'except'){
                 m.'except'.addAll excludedProps
                 def props= domainClass.persistentProperties.findAll {
                     !(it.name in m.'except')
                 }
                 props.each{
                     map[it.name]= delegate."${it.name}"
                 }
             }
             return map
         }
     }
  }
  def destroy = {
  }
}

If you know how to create our own plugin, then just create one plugin for this, so that you can use it across all the grails applications.


If you want to only include specific properties all the time, you would really want to use the ObjectMarshaller interface. See this article for more details.


If you simply want to render an instance of MyClass as JSON, excluding certain properties, here's a solution that uses the JSONBuilder class provided by Grails

import grails.web.JSONBuilder

class MyClassController{

    def someAction = {

        def myClass = new MyClass()

        def builder = new JSONBuilder.build {
            myClass.properties.each {propName, propValue ->

            // Properties excluded from the JSON
            def excludes = ['class', 'metaClass', 'val3']

            if (!excludes.contains(propName)) {

                setProperty(propName, propValue)
            }
        }
        render(text: builder.toString(), contentType: 'application/json')
     }
}


Or, you could just create a map of the properties you wanted, then encode them as JSON

Map m = [ 'val1', 'val2' ].inject( [:] ) { map, val -> map."$val" = a."$val" ; map }
render m as JSON

To exclude properties, you would need to do something like this (UNTESTED)

def exclude = [ 'val3' ]
Map m = new DefaultGrailsDomainClass( MyClass.class ).properties.findAll {
  !( it.name in exclude )
}.inject( [:] ) { map, val ->
  map."$val.name" = a."$val.name" ; map
}
render m as JSON


The JSON Exclusion Marshaller Plugin

I needed to solve this problem recently. I went ahead and packaged the solution into a plugin that allows you to easily exclude class properties from the JSON converter's output. It is available on the Grails Plugin Portal.

After you install the plugin, you will have access to a method on the grails.converters.JSON class called excludeFor*().

More extensive documentation can be found here: How to use the JSON Exclusion Marshaller

But basically it can be used as such:

import grails.converters.JSON

def json, resultTeachersWillSee, resultOtherStudentsWillSee

// Given a TestStudent Domain Class
def student = new TestStudent([
    firstName: "Tobias",
    lastName: "Funke",
    gradePointAverage: 3.6,
    studentID: "FS-210-7312",
    socialSecurityNumber: "555-55-5555"
])
student.save(flush: true)

// When
JSON.excludeForTeachers(TestStudent, ['socialSecurityNumber', 'id', 'class'])

JSON.use('excludeForTeachers') {
    json = new JSON(student)
}
resultTeachersWillSee = json.toString()

// Then
assert resultTeachersWillSee == '{"firstName":"Tobias",
       "gradePointAverage":3.6, "lastName":"Funke", 
       "studentID":"FS-210-7312"}'



// And When
JSON.excludeForOtherStudents(TestStudent, ['gradePointAverage', 'studentID', 
     'socialSecurityNumber', 'id', 'class'])

JSON.use('excludeForOtherStudents') {
    json = new JSON(student)
}
resultOtherStudentsWillSee = json.toString()

// Then
assert resultOtherStudentsWillSee == '{"firstName":"Tobias",
       "lastName":"Funke"}'

JSON.excludeForTeachers(...) creates a named object marshaller called "excludeForTeachers". The marshaller excludes three properties of the student object from the resulting JSON output. the 'socialSecurityNumber' property is explicitly defined in the class, while the 'id' property was added by GORM behind the scenes. In any case, teachers don't need to see any of those properties.

The plugin is serving me well... I hope others find it helpful too.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜