2011-10-09 86 views
11

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

我有两个问题:

  • 如何编写一个Deserializer所有ImmutableList<XXX>工作?
  • 如何注册全部ImmutableList<XXX>

回答

10

更新:有https://github.com/acebaggins/gson-serializers涵盖许多番石榴集合:

  • ImmutableList
  • ImmutableSet
  • ImmutableSortedSet
  • ImmutableMap
  • ImmutableSortedMap

如何编写一个解串器对所有ImmutableList工作?

的想法很简单,变换传递Type表示ImmutableList<T>为代表List<T>一个Type,使用内置的Gson的能力,以创建一个List并将其转换为一个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); 
    } 
} 

有多种ParameterizedTypeImpl班在我使用Java库,但他们都不打算公开使用。我用sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl进行了测试。

如何为所有ImmutableList注册它?

这部分是微不足道的,注册的第一个参数是java.lang.reflect.Type其误导我使用ParameterizedType,其中仅使用Class这项工作:

final Gson gson = new GsonBuilder() 
    .registerTypeAdapter(ImmutableList.class, myJsonDeserializer) 
    .create(); 
+0

我们可以避免使用ParameterizedTypeImpl吗?例如使用smth如: final列表 list = context.deserialize(json,List.class); –

+0

@Alexander Bezrodniy:恐怕不可能。你可以通过使用'TypeAdapter >'来避免这一切,但是你必须写一些其他的样板代码:1。即使默认实现已经足够,也可以实现'write',2.处理'read'中的'null'。这都是一些低级别的东西。 – maaartinus

+0

我想我现在明白你的问题了。你不能忽略泛型;没有他们的列表内容不能正确反序列化。 – maaartinus

2

@maaartinus已经涵盖了第二个问题,所以我“会发布一个基于互补番石榴,解决了第一个问题,它不需要ParametrizedTypeImpl

public final class ImmutableListDeserializer implements JsonDeserializer<ImmutableList<?>> { 
    @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 <E> TypeToken<List<E>> listOf(final Type arg) { 
    return new TypeToken<List<E>>() {} 
     .where(new TypeParameter<E>() {}, (TypeToken<E>) TypeToken.of(arg)); 
    } 
} 
7

还有一个小鬼lementation 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); 
}