使用Gson反序列化ImmutableList
我正在使用相当多的不可变集合,我很好奇如何使用Gson对它们进行反序列化。 由于没有人回答我自己找到了解决方案,我正在简化问题并提出自己的答案。
我有两个问题:
- 如何编写一个适用于所有
ImmutableList
的单个Deserializer
? - 如何为所有
ImmutableList
?
更新:有https://github.com/acebaggins/gson-serializers ,涵盖了许多番石榴系列:
-
ImmutableList
-
ImmutableSet
-
ImmutableSortedSet
-
ImmutableMap
-
ImmutableSortedMap
如何编写一个适用于所有ImmutableList的单个反序列化器?
这个想法很简单,将表示ImmutableList
的传递Type
转换为表示List
的Type
,使用内置Gson
的function创建List
并将其转换为ImmutableList
。
class MyJsonDeserializer implements JsonDeserializer> { @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); } }
我使用的Java库中有多个ParameterizedTypeImpl
类,但没有一个用于公共用途。 我用sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
测试了它。
如何为所有ImmutableList注册?
那部分是微不足道的,注册的第一个参数是java.lang.reflect.Type
,它误导我使用ParameterizedType
,只需使用Class
就可以完成这项任务:
final Gson gson = new GsonBuilder() .registerTypeAdapter(ImmutableList.class, myJsonDeserializer) .create();
还有一个没有ParameterizedTypeImpl的实现
@Override public ImmutableList> deserialize(final JsonElement json, final Type type, final JsonDeserializationContext context) throws JsonParseException { @SuppressWarnings("unchecked") final TypeToken> immutableListToken = (TypeToken>) TypeToken.of(type); final TypeToken super ImmutableList>> listToken = immutableListToken.getSupertype(List.class); final List> list = context.deserialize(json, listToken.getType()); return ImmutableList.copyOf(list); }
@maaartinus已经涵盖了第二个问题,所以我将在第一个问题上发布一个基于Guava的补充解决方案,不需要ParametrizedTypeImpl
public final class ImmutableListDeserializer implements JsonDeserializer> { @Override public ImmutableList> deserialize(final JsonElement json, final Type type, final JsonDeserializationContext context) throws JsonParseException { final Type[] typeArguments = ((ParameterizedType) type).getActualTypeArguments(); final Type parameterizedType = listOf(typeArguments[0]).getType(); final List> list = context.deserialize(json, parameterizedType); return ImmutableList.copyOf(list); } private static TypeToken> listOf(final Type arg) { return new TypeToken>() {} .where(new TypeParameter () {}, (TypeToken ) TypeToken.of(arg)); } }