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();