Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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) ?

like image 447
Bella Avatar asked May 09 '11 11:05

Bella


4 Answers

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.

like image 129
Jason Stonebraker Avatar answered Sep 27 '22 22:09

Jason Stonebraker


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.

like image 29
Gregg Avatar answered Nov 17 '22 23:11

Gregg


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.

like image 5
Nirmal Avatar answered Nov 17 '22 22:11

Nirmal


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')
     }
}
like image 3
Dónal Avatar answered Nov 17 '22 23:11

Dónal