使用Gson反序列化ImmutableList

我正在使用相当多的不可变集合,我很好奇如何使用Gson对它们进行反序列化。 由于没有人回答我自己找到了解决方案,我正在简化问题并提出自己的答案。

我有两个问题:

  • 如何编写一个适用于所有ImmutableList的单个Deserializer
  • 如何为所有ImmutableList

更新:有https://github.com/acebaggins/gson-serializers ,涵盖了许多番石榴系列:

  • ImmutableList
  • ImmutableSet
  • ImmutableSortedSet
  • ImmutableMap
  • ImmutableSortedMap

如何编写一个适用于所有ImmutableList的单个反序列化器?

这个想法很简单,将表示ImmutableList的传递Type转换为表示ListType ,使用内置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> 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)); } }