Quantcast

Removing class attributes from JSON responses

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Removing class attributes from JSON responses

Greg Pagendam-Turner
Hi,

I'm using Grails 2.0.4. I'm trying to remove the 'class' attributes from
marshalled JSON responses.

I've copied and renamed the Grails GroovyBeenMarshaller:

package liftyourgame.grails

import grails.converters.JSON;
import groovy.lang.GroovyObject;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import
org.codehaus.groovy.grails.web.converters.exceptions.ConverterException;
import
org.codehaus.groovy.grails.web.converters.marshaller.ObjectMarshaller;
import org.codehaus.groovy.grails.web.json.JSONWriter;
import org.springframework.beans.BeanUtils;

public class NoClassNameObjectMarshaller implements ObjectMarshaller<JSON> {

     public boolean supports(Object object) {
         return object instanceof GroovyObject;
     }

     public void marshalObject(Object o, JSON json) throws
ConverterException {
         JSONWriter writer = json.getWriter();
         try {
             writer.object();
             for (PropertyDescriptor property :
BeanUtils.getPropertyDescriptors(o.getClass())) {
                 String name = property.getName();
                 Method readMethod = property.getReadMethod();
                 if (readMethod != null && !(name.equals("metaClass"))) {
                     Object value = readMethod.invoke(o, (Object[]) null);
                     writer.key(name);
                     json.convertAnother(value);
                 }
             }
             for (Field field : o.getClass().getDeclaredFields()) {
                 int modifiers = field.getModifiers();
                 if (Modifier.isPublic(modifiers) &&
!(Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers))) {
                     writer.key(field.getName());
                     json.convertAnother(field.get(o));
                 }
             }
             writer.endObject();
         }
         catch (ConverterException ce) {
             throw ce;
         }
         catch (Exception e) {
             throw new ConverterException("Error converting Bean with
class " + o.getClass().getName(), e);
         }
     }
}

I was just going to get this working before I add in the
!name.equals("class") bit.

If I register my converter in Bootstrap init with:
JSON.registerObjectMarshaller(new NoClassNameObjectMarshaller())

I get the following error when Marshalling occurs:
| Error 2012-06-26 09:44:11,771 [http-bio-8080-exec-9] ERROR
errors.GrailsExceptionResolver  - IllegalAccessException occurred when
processing request: [GET] /liftyourgame/quote
Class
org.codehaus.groovy.grails.web.converters.marshaller.json.GenericJavaBeanMarshaller
can not access a member of class
org.springframework.beans.GenericTypeAwarePropertyDescriptor with
modifiers "public". Stacktrace follows:
Message: Class
org.codehaus.groovy.grails.web.converters.marshaller.json.GenericJavaBeanMarshaller
can not access a member of class
org.springframework.beans.GenericTypeAwarePropertyDescriptor with
modifiers "public"
     Line | Method
->>  199 | value            in grails.converters.JSON
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|    162 | convertAnother   in     ''
|    199 | value . . . . .  in     ''
|    162 | convertAnother   in     ''
|    199 | value . . . . .  in     ''
|    162 | convertAnother   in     ''
|     32 | marshalObject .  in
liftyourgame.grails.NoClassNameObjectMarshaller
|    199 | value            in grails.converters.JSON
|    162 | convertAnother . in     ''
|     32 | marshalObject    in
liftyourgame.grails.NoClassNameObjectMarshaller
|    199 | value . . . . .  in grails.converters.JSON
|    134 | render           in     ''
|    150 | render . . . . . in     ''
|     13 | show             in liftyourgame.grails.QuoteController
|     55 | doFilter . . . . in org.apache.shiro.grails.SavedRequestFilter
|    449 | executeChain     in
org.apache.shiro.web.servlet.AbstractShiroFilter
|    365 | call . . . . . . in
org.apache.shiro.web.servlet.AbstractShiroFilter$1
|     90 | doCall           in
org.apache.shiro.subject.support.SubjectCallable
|     83 | call . . . . . . in     ''
|    380 | execute          in
org.apache.shiro.subject.support.DelegatingSubject
|    362 | doFilterInternal in
org.apache.shiro.web.servlet.AbstractShiroFilter
|    125 | doFilter         in
org.apache.shiro.web.servlet.OncePerRequestFilter
|   1110 | runWorker . . .  in java.util.concurrent.ThreadPoolExecutor
|    603 | run              in
java.util.concurrent.ThreadPoolExecutor$Worker
^    722 | run . . . . . .  in java.lang.Thread



Any ideas please?

Regards,

Greg




---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: Removing class attributes from JSON responses

Miles Burton-2
I'm *less* than happy about this solution but it does allow you to
remove unnecessary properties from being marshed.

 // Move to json converter
    private excludedProperties = ['class', 'metaClass', 'dateOfBirth',
'dateOfDeath']

    private String toJson(Person person) {

        JSONBuilder builder = new JSONBuilder()

        return  builder.build {
            person.properties.each {propName, propValue ->

                if (!(propName in excludedProperties)) {
                    setProperty(propName, propValue)
                }
            }
            setProperty("personId", person.id)
            setProperty("dateOfBirth", person.dateOfBirth.format("yyyy-MM-dd"))
            setProperty("dateOfDeath", person.dateOfDeath.format("yyyy-MM-dd"))
        }
    }

On Tue, Jun 26, 2012 at 12:45 AM, Greg Pagendam-Turner
<[hidden email]> wrote:

> Hi,
>
> I'm using Grails 2.0.4. I'm trying to remove the 'class' attributes from
> marshalled JSON responses.
>
> I've copied and renamed the Grails GroovyBeenMarshaller:
>
> package liftyourgame.grails
>
> import grails.converters.JSON;
> import groovy.lang.GroovyObject;
>
> import java.beans.PropertyDescriptor;
> import java.lang.reflect.Field;
> import java.lang.reflect.Method;
> import java.lang.reflect.Modifier;
>
> import
> org.codehaus.groovy.grails.web.converters.exceptions.ConverterException;
> import
> org.codehaus.groovy.grails.web.converters.marshaller.ObjectMarshaller;
> import org.codehaus.groovy.grails.web.json.JSONWriter;
> import org.springframework.beans.BeanUtils;
>
> public class NoClassNameObjectMarshaller implements ObjectMarshaller<JSON> {
>
>    public boolean supports(Object object) {
>        return object instanceof GroovyObject;
>    }
>
>    public void marshalObject(Object o, JSON json) throws ConverterException
> {
>        JSONWriter writer = json.getWriter();
>        try {
>            writer.object();
>            for (PropertyDescriptor property :
> BeanUtils.getPropertyDescriptors(o.getClass())) {
>                String name = property.getName();
>                Method readMethod = property.getReadMethod();
>                if (readMethod != null && !(name.equals("metaClass"))) {
>                    Object value = readMethod.invoke(o, (Object[]) null);
>                    writer.key(name);
>                    json.convertAnother(value);
>                }
>            }
>            for (Field field : o.getClass().getDeclaredFields()) {
>                int modifiers = field.getModifiers();
>                if (Modifier.isPublic(modifiers) &&
> !(Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers))) {
>                    writer.key(field.getName());
>                    json.convertAnother(field.get(o));
>                }
>            }
>            writer.endObject();
>        }
>        catch (ConverterException ce) {
>            throw ce;
>        }
>        catch (Exception e) {
>            throw new ConverterException("Error converting Bean with class "
> + o.getClass().getName(), e);
>        }
>    }
> }
>
> I was just going to get this working before I add in the
> !name.equals("class") bit.
>
> If I register my converter in Bootstrap init with:
> JSON.registerObjectMarshaller(new NoClassNameObjectMarshaller())
>
> I get the following error when Marshalling occurs:
> | Error 2012-06-26 09:44:11,771 [http-bio-8080-exec-9] ERROR
> errors.GrailsExceptionResolver  - IllegalAccessException occurred when
> processing request: [GET] /liftyourgame/quote
> Class
> org.codehaus.groovy.grails.web.converters.marshaller.json.GenericJavaBeanMarshaller
> can not access a member of class
> org.springframework.beans.GenericTypeAwarePropertyDescriptor with modifiers
> "public". Stacktrace follows:
> Message: Class
> org.codehaus.groovy.grails.web.converters.marshaller.json.GenericJavaBeanMarshaller
> can not access a member of class
> org.springframework.beans.GenericTypeAwarePropertyDescriptor with modifiers
> "public"
>    Line | Method
> ->>  199 | value            in grails.converters.JSON
> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
> |    162 | convertAnother   in     ''
> |    199 | value . . . . .  in     ''
> |    162 | convertAnother   in     ''
> |    199 | value . . . . .  in     ''
> |    162 | convertAnother   in     ''
> |     32 | marshalObject .  in
> liftyourgame.grails.NoClassNameObjectMarshaller
> |    199 | value            in grails.converters.JSON
> |    162 | convertAnother . in     ''
> |     32 | marshalObject    in
> liftyourgame.grails.NoClassNameObjectMarshaller
> |    199 | value . . . . .  in grails.converters.JSON
> |    134 | render           in     ''
> |    150 | render . . . . . in     ''
> |     13 | show             in liftyourgame.grails.QuoteController
> |     55 | doFilter . . . . in org.apache.shiro.grails.SavedRequestFilter
> |    449 | executeChain     in
> org.apache.shiro.web.servlet.AbstractShiroFilter
> |    365 | call . . . . . . in
> org.apache.shiro.web.servlet.AbstractShiroFilter$1
> |     90 | doCall           in
> org.apache.shiro.subject.support.SubjectCallable
> |     83 | call . . . . . . in     ''
> |    380 | execute          in
> org.apache.shiro.subject.support.DelegatingSubject
> |    362 | doFilterInternal in
> org.apache.shiro.web.servlet.AbstractShiroFilter
> |    125 | doFilter         in
> org.apache.shiro.web.servlet.OncePerRequestFilter
> |   1110 | runWorker . . .  in java.util.concurrent.ThreadPoolExecutor
> |    603 | run              in
> java.util.concurrent.ThreadPoolExecutor$Worker
> ^    722 | run . . . . . .  in java.lang.Thread
>
>
>
> Any ideas please?
>
> Regards,
>
> Greg
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>   http://xircles.codehaus.org/manage_email
>
>

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: Removing class attributes from JSON responses

sergiomichels
In reply to this post by Greg Pagendam-Turner
Hi Greg, have you solved this? I have the same issue, trying to marshall a command bean using my custom Groovy Marshaller.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: Removing class attributes from JSON responses

kuras
We have faced the same problem after migrating our application from Grails 1.3.7 to 2.0.4.

We had a custom marshaller which used to exclude 'class' property from being visible in JSON. The error occured with classes which had @Validateable annotation on them. This annotation not only adds a validate() method to the class but also introduces a property called 'errors'. While using Grails 1.3.7 this property was not visible in the final json even though we had no config to exclude it explicitly.

Once we upgraded to 2.0.4, marshalling an object with @Validateable started to result in exactly the same exception as Greg has mentioned in his post. We traced that it happens when converting 'errors' property. Luckily for us, we didn't need this property in the json. Hence, we excluded 'errors' property in our marshaller and exception disappeared.

Sergio, since you domain objects have the same 'errors' property as @Validateable objects, you could also try to exclude it from marshalling, if this is acceptable for you.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: Removing class attributes from JSON responses

sergiomichels
Hi, actually I'm using the Grails GSON plugin https://github.com/robfletcher/grails-gson

With this, the errors goes away, and also you have the option of register custom adapters for custom user types.

--
Sérgio Michels


On Fri, Mar 29, 2013 at 2:25 PM, kuras [via Grails] <[hidden email]> wrote:
We have faced the same problem after migrating our application from Grails 1.3.7 to 2.0.4.

We had a custom marshaller which used to exclude 'class' property from being visible in JSON. The error occured with classes which had @Validateable annotation on them. This annotation not only adds a validate() method to the class but also introduces a property called 'errors'. While using Grails 1.3.7 this property was not visible in the final json even though we had no config to exclude it explicitly.

Once we upgraded to 2.0.4, marshalling an object with @Validateable started to result in exactly the same exception as Greg has mentioned in his post. We traced that it happens when converting 'errors' property. Luckily for us, we didn't need this property in the json. Hence, we excluded 'errors' property in our marshaller and exception disappeared.

Sergio, since you domain objects have the same 'errors' property as @Validateable objects, you could also try to exclude it from marshalling, if this is acceptable for you.


If you reply to this email, your message will be added to the discussion below:
http://grails.1312388.n4.nabble.com/Removing-class-attributes-from-JSON-responses-tp4630631p4643058.html
To unsubscribe from Removing class attributes from JSON responses, click here.
NAML

Loading...