... until the collector arrives ...

This "blog" is really just a scratchpad of mine. There is not much of general interest here. Most of the content is scribbled down "live" as I discover things I want to remember. I rarely go back to correct mistakes in older entries. You have been warned :)

2012-10-05

Serializing Run-Time Types with gson

gson is a JSON serialization libary for Java. It is optimized for round-trip serialization and deserialization between Java and JSON representations of objects. To support such round trips, the serializer operates upon the static types of an object tree. As a result, the dynamic (run-time) types of objects are generally ignored.

This can be inconvenient for simple, output-only serialization scenarios. Consider what happens if we try to serialize, say, a List<MyClass>. When gson serializes this list, the output will include each element's fields from the declared type (MyClass). Fields from each element's run-time type will not be serialized. If MyClass is an interface, then there are no declared fields to serialize. Such elements will always be serialized as an empty JSON object ({}).

One way to work around this is to implement a TypeAdapterFactory that handles all interface types:

final class MyAdapterFactory implements TypeAdapterFactory {

    @Override
    public  TypeAdapter create(final Gson gson, TypeToken type) {
        Class rawType = type.getRawType();
        if (rawType.isInterface()) {
            return new TypeAdapter() {

                @Override
                public void write(JsonWriter out, T value) {
                    Type valueType = null == value ? Object.class : value.getClass();
                    gson.toJson(value, valueType, out);
                }

                @Override
                public T read(JsonReader in) {
                    // we only care about serialization in this scenario
                    throw new IllegalStateException();
                }
            };
        }
        return null;
    }
}

This adapter factory will delegate serialization of an object of any interface class to a custom TypeAdapter that inspects the run-time type of the object.

The factory is installed using GsonBuilder:

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapterFactory(new MyAdapterFactory());
// ...
Gson gson = gsonBuilder.create();

Blog Archive