Десериализация ImmutableList с помощью Gson - PullRequest
11 голосов
/ 10 октября 2011

Я использую довольно много неизменных коллекций, и мне любопытно, как десериализовать их с помощью Gson.Поскольку никто не ответил, и я сам нашел решение, я упрощаю вопрос и представляю свой собственный ответ.

У меня было две проблемы:

  • Как написать один Deserializer работает для всех ImmutableList<XXX>?
  • Как зарегистрировать его для всех ImmutableList<XXX>?

Ответы [ 3 ]

10 голосов
/ 15 октября 2011

Обновление: есть https://github.com/acebaggins/gson-serializers, который охватывает множество коллекций гуавы:

  • ImmutableList
  • ImmutableSet
  • ImmutableSortedSet
  • ImmutableMap
  • ImmutableSortedMap

Как написать один десериализатор, работающий для всех 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);
    }
}

В библиотеках Java есть несколько ParameterizedTypeImpl классов, которые я использую, но ни один из них не предназначен для публичного использования.Я протестировал его с помощью sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl.

Как зарегистрировать его для всех ImmutableList?

Эта часть тривиальна, первый аргумент для регистрации - java.lang.reflect.Type, что вводит в заблуждениемне использовать ParameterizedType, где просто с помощью Class делает работу:

final Gson gson = new GsonBuilder()
    .registerTypeAdapter(ImmutableList.class, myJsonDeserializer)
    .create();
8 голосов
/ 16 февраля 2014

Еще одна реализация без 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);
}
2 голосов
/ 10 февраля 2014

@ maaartinus уже рассмотрел второй вопрос, поэтому я опубликую дополнительное решение на основе Guava для первого вопроса, для которого не требуется 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));   
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...