You are hereArray / GwtProJsonSerializer and Jackson

GwtProJsonSerializer and Jackson


By heath - Posted on 13 March 2012

I recently had to deal with some of the JSON that was passed back from the GwtProJsonSerializer in our web tier. It is in Groovy, so I thought I might be able to use JSON.parse. While I could use it for some instances, I wanted to reuse some components that dealt with a class hierarchy. In order to do that, I needed to deserialize the JSON into the original classes.

After a little research, I discovered the Jackson project for doing just that. However, it uses annotations to reference derived classes. This is a problem because I don't want to include the Jackson jar in my GWT deployment if it would even work. As one would figure, there was more than one way to do things. Jackson allows you to setup additional "deserializers" so you can insert some of your own code to handle special situations. Here is how I did things to handle getting the class to deserialize from the "class" attribute in the output of GwtProJsonSerializer. I am using Groovy, but I made it more Java-esque to demonstrate how to do it with generics.

package com.ids.emr.docgen.configuration

import org.codehaus.jackson.map.deser.StdDeserializer
import org.codehaus.jackson.JsonParser
import org.codehaus.jackson.map.DeserializationContext
import org.codehaus.jackson.JsonNode
import org.codehaus.jackson.node.ObjectNode
import org.codehaus.jackson.map.ObjectMapper
import java.util.Map.Entry
import org.codehaus.jackson.Version
import org.codehaus.jackson.map.module.SimpleModule

class GwtProJsonDeserializer extends StdDeserializer {
    GwtProJsonDeserializer(Class<? extends T> clazz){
        super(clazz)
    }

    @Override
    T deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) {
        ObjectMapper mapper = (ObjectMapper) jsonParser.getCodec()
        ObjectNode root = (ObjectNode) mapper.readTree(jsonParser)
        Iterator> elementsIterator = root.getFields()
        while (elementsIterator.hasNext()) {
            Entry element = elementsIterator.next()
            if (element.getKey() == "class") {
                root.remove("class")
                Class<? extends T> configClass = Thread.currentThread().contextClassLoader.loadClass(element.getValue().textValue)
                return mapper.readValue(root, configClass)
            }
        }

        return null
    }

    static  ObjectMapper createMapper(Class<? extends T> clazz) {
        def deserializer = new GwtProJsonDeserializer(clazz)
        SimpleModule module = new SimpleModule("GwtProJsonDeserializerModule",new Version(0,0,1,""))
        module.addDeserializer(clazz, deserializer)
        def mapper = new ObjectMapper()
        mapper.registerModule(module)
        return mapper
    }
}

To use it you use createMapper to create your ObjectMapper and call readValue on it as in the ObjectMapper tutorial.

Tags