how to register a custom json marshaller in grails

10,727

Solution 1

this is what i do for custom JSON marshaling in the Bootstrap init closure:

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['id'] = delegate.id
                    map[it.name] = delegate."${it.name}"
                }
            }
            return map
        }



    }
    JSON.registerObjectMarshaller(Date) {
        return it?.format("dd.MM.yyyy")
    }
    JSON.registerObjectMarshaller(User) {
        def returnArray = [:]
        returnArray['username'] = it.username
        returnArray['userRealName'] = it.userRealName 
        returnArray['email'] = it.email
        return returnArray
    }
    JSON.registerObjectMarshaller(Role) {
        def returnArray = [:]
        returnArray['authority'] = it.authority
        return returnArray
    }
     JSON.registerObjectMarshaller(Person) {
        return it.part(except: ['fieldX', 'fieldY'])
    }}

you see that i have custom marshallers for the Date, Use, Person, and Role Class

Solution 2

I found this post while trying to find out a proper way for the marshaller registering. The biggest difference compared to Nils' answer is that this solution leaves BootStrap.groovy intact, which is nice.

http://compiledammit.com/2012/08/16/custom-json-marshalling-in-grails-done-right/

Share:
10,727
vijay tyagi
Author by

vijay tyagi

Updated on June 30, 2022

Comments

  • vijay tyagi
    vijay tyagi almost 2 years

    I am trying to register a custom json marshaller like this

     JSON.createNamedConfig("dynamic",{ 
                def m = new CustomJSONSerializer()
                JSON.registerObjectMarshaller(Idf, 1, { instance, converter -> m.marshalObject(instance, converter) }) 
                })
    
    and then using it like this
    
        JSON.use("dynamic"){
                render inventionList as JSON
                }
    

    but I am not sure if my custom serializer is being used because when I am debugging control never goes to marshalObject function of my custom serializer

    My custom serializer is as follows

    import grails.converters.deep.JSON
    import java.beans.PropertyDescriptor
    import java.lang.reflect.Field
    import java.lang.reflect.Method
    import org.codehaus.groovy.grails.web.converters.exceptions.ConverterException
    import org.codehaus.groovy.grails.web.converters.marshaller.json.GroovyBeanMarshaller
    import org.codehaus.groovy.grails.web.json.JSONWriter
    
    class CustomJSONSerializer extends GroovyBeanMarshaller{
        public boolean supports(Object object) {
            return object instanceof GroovyObject;
        }
    
        public void marshalObject(Object o, JSON json) throws ConverterException {
            JSONWriter writer = json.getWriter();
            println 'properties '+BeanUtils.getPropertyDescriptors(o.getClass())
            for(PropertyDescriptor property:BeanUtils.getProperyDescriptors(o.getClass())){
                    println 'property '+property.getName()
                }
            try {
                writer.object();
                for (PropertyDescriptor property : BeanUtils.getPropertyDescriptors(o.getClass())) {
                    String name = property.getName();
                    Method readMethod = property.getReadMethod();
                    if (readMethod != null && !(name.equals("metaClass")) && readMethod.getName()!='getSpringSecurityService') {
                        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);
            }
        }
    
    
    }
    

    Is it possible to debug the serializer? If not then how can I exclude a property from serialization? There's some property which throws exception during serialization.

  • cdeszaq
    cdeszaq over 11 years
    The article you linked to is a much better, cleaner approach. To help deal with link rot, please consider quoting the most relevant bits of the article here in your answer.
  • adeady
    adeady about 7 years
    site appears to be down these days.