I'm using quite a few immutable collections and I'm curious how to deserialize them using Gson. As nobody answered and I've found the solution myself, I'm simplifying the question and presenting my own answer.
I had two problems:
Deserializer
working for all ImmutableList<XXX>
?ImmutableList<XXX>
?Update: There's https://github.com/acebaggins/gson-serializers which covers many guava collections:
ImmutableList
ImmutableSet
ImmutableSortedSet
ImmutableMap
ImmutableSortedMap
How to write a single Deserializer working for all ImmutableList?
The idea is simple, transform the passed Type
representing an ImmutableList<T>
into a Type
representing List<T>
, use the build-in Gson
's capability to create a List
and convert it to an ImmutableList
.
class MyJsonDeserializer implements JsonDeserializer<ImmutableList<?>> {
@Override
public ImmutableList<?> deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {
final Type type2 = ParameterizedTypeImpl.make(List.class, ((ParameterizedType) type).getActualTypeArguments(), null);
final List<?> list = context.deserialize(json, type2);
return ImmutableList.copyOf(list);
}
}
There are multiple ParameterizedTypeImpl
classes in Java libraries I use, but none of them intended for public usage. I tested it with sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
.
How to register it for all ImmutableList?
That part is trivial, the first argument to register is java.lang.reflect.Type
which mislead me to using ParameterizedType
, where simply using Class
does the job:
final Gson gson = new GsonBuilder()
.registerTypeAdapter(ImmutableList.class, myJsonDeserializer)
.create();
One more implementation without ParameterizedTypeImpl
@Override
public ImmutableList<?> deserialize(final JsonElement json, final Type type, final JsonDeserializationContext context) throws JsonParseException {
@SuppressWarnings("unchecked")
final TypeToken<ImmutableList<?>> immutableListToken = (TypeToken<ImmutableList<?>>) TypeToken.of(type);
final TypeToken<? super ImmutableList<?>> listToken = immutableListToken.getSupertype(List.class);
final List<?> list = context.deserialize(json, listToken.getType());
return ImmutableList.copyOf(list);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With