简体   繁体   English

使用Gson反序列化ImmutableList

[英]Deserializing ImmutableList using Gson

I'm using quite a few immutable collections and I'm curious how to deserialize them using Gson. 我正在使用许多不可变的集合,并且很好奇如何使用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: 我有两个问题:

  • How to write a single Deserializer working for all ImmutableList<XXX> ? 如何编写适用于所有ImmutableList<XXX>的单个Deserializer
  • How to register it for all ImmutableList<XXX> ? 如何为所有ImmutableList<XXX>注册它?

Update: There's https://github.com/acebaggins/gson-serializers which covers many guava collections: 更新:有https://github.com/acebaggins/gson-serializers ,其中涵盖了许多番石榴集合:

  • ImmutableList
  • ImmutableSet
  • ImmutableSortedSet
  • ImmutableMap
  • ImmutableSortedMap

How to write a single Deserializer working for all ImmutableList? 如何编写适用于所有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 . 这个想法是简单,变换传递Type表示ImmutableList<T>Type表示List<T>中,使用内置的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);
    }
}

There are multiple ParameterizedTypeImpl classes in Java libraries I use, but none of them intended for public usage. 我使用的Java库中有多个ParameterizedTypeImpl类,但是它们都不适合公共使用。 I tested it with sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl . 我使用sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl测试了它。

How to register it for all ImmutableList? 如何为所有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: 这部分很简单,register的第一个参数是java.lang.reflect.Type ,它使我误以为使用ParameterizedType ,而仅使用Class完成工作:

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

One more implementation without ParameterizedTypeImpl 没有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);
}

@maaartinus already covered the second question, so I'll post a complementary Guava-based solution to the first question which doesn't require ParametrizedTypeImpl @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));   
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM