Making GWT JSON not Quite so Painful

I've been using GWT to resurface interfaces of a variety of legacy applications -- J2EE, PHP, Rails -- and more often than not that means working with JSON returned from the server. One thing that I've found is that GWT's JSON support is kind of chatty. That is, you have to write a bunch of code like this:

JSONValue root = JSONParser.parse(json);
JSONObject obj = root.isObject();
if (obj != null) {
    JSONValue map = obj.get("map");
    if (map != null) {
        JSONArray arr = map.isArray();
        if (arr != null) {
            if (arr.size() > 1) {
                JSONValue strval = arr.get(1);
                if (strval != null) {
                    JSONString str = strval.isString();
                    if (str != null) {
                        String s = str.stringValue();
                        // do something with the string
                    }
                }
            }
        }
    }
}

Yikes! Just to get the string in the second array item in the "map" key of the top level object. Truth is, most of the JSON I'm getting back is fairly predictable. And if it's not in that predictable form, it's an error that the client code can't recover from. I'd like to be able to write something like String result = obj.get("map").get(1).stringValue() without having to worry about NullPointerException's cropping up all over the place.

One option is to do what other developers have done, which is to use JNSI to roll out own JSON handling code. But that defeats the purpose of a framework like GWT. I'd rather leverage what's already there than come up with my own code which I'll then have to support.

So I've written up a little helper class called JSONWrapper that lets you do the above style code. It's pretty simple. As it's name suggests, it wraps a JSONValue object and lets you perform selections on it that return other JSONWrapper objects. Thus you can string together the method calls with method chaining (ala JQuery).

public class JSONWrapper {
    private JSONValue value;

    public JSONWrapper(JSONValue value) {
        this.value = value;
    }

    public JSONValue getValue() {
        return value;
    }

    public final static JSONWrapper NULL = new JSONWrapper(null);

    public boolean isValid() {
        return (value != null);
    }
    [...]
}

If at any point a request results in an invalid value, such as requesting an array index from a non-array, we return a JSONWrapper with null as its value. We reuse the NULL constant to save on some memory.

    public JSONWrapper get(int index) {
        if (index < 0) {
            return NULL;
        }
        if (value == null) {
            return NULL;
        }

        JSONArray arr = value.isArray();
        if (arr == null) {
            return NULL;
        }
        if (index >= arr.size()) {
            return NULL;
        }
        JSONValue retval = arr.get(index);
        if (retval == null) {
            return NULL;
        }

        return new JSONWrapper(retval);
    }

We want to distinguish between JSONNull and our null values, since sometimes the backend will really want to pass a JSON null.

I'll put this up on google code in a day or two. It's just one class (though one I find really useful). Perhaps this shouldn't be a module but rather find a home in another library.

Some other things I've been working on: StringReader for GWT and a simple model Observer/Observable library.

Update: The lib is now available on Google Code.

Related Services: Ajax Rich Internet Applications, Java Application Development, Custom Software Development