Тип Java Generic как аргумент для GSON

В GSON для получения списка объектов, которые вы делаете

Gson gson = new Gson();
Type token = new TypeToken<List<MyType>>(){}.getType();
return gson.fromJson(json, token);

Он отлично работает, но я хочу , чтобы идти дальше , и у меня // общие функции общественности < T > Список < T > fromJSonList ( строка JSON , класс < T > типа ) { Gson gson = новый Gson (); Тип collectionType = new TypeToken < List < T >> () {}. getType (); return gson . fromJson ( json , collectionType ); } // вызов списка < MyType > myTypes = синтаксический анализатор . fromJSonList ( jsonString , MyType . class ); параметризован, поэтому я могу иметь общую функцию для анализа списка объектов с помощью этого кода

<T>

Печально возвращает массив StringMaps, а не ParameterizedType. T интерпретируется как другой общий тип, а не мой тип. Любое обходное решение?

java,generics,gson,

43

Ответов: 9


41

Дженерики работают во время компиляции. Причина, по которой работают маркеры супертипа, заключается в том, что (анонимные) внутренние классы могут обращаться к аргументам типа к их универсальным суперклассам (суперинтерфейсам), которые, в свою очередь, хранятся непосредственно в метаданных байт-кода.

Как только ваш исходный файл .java скомпилирован, параметр типа, очевидно, выброшен. Так как во время компиляции это неизвестно, он не может быть сохранен в байт-коде, поэтому он стирается, и Gson не может его прочитать.class ListOfSomething<X> implements ParameterizedType { private Class<?> wrapped; public ListOfSomething(Class<X> wrapped) { this.wrapped = wrapped; } public Type[] getActualTypeArguments() { return new Type[] {wrapped}; } public Type getRawType() { return List.class; } public Type getOwnerType() { return null; } }

ОБНОВИТЬ

После ответа newacct я попытался реализовать то, что он предложил в своем варианте 2, то есть реализовать a getFromJsonList(). Код выглядит следующим образом (вот базовый тест ):

public List<T> fromJsonList(String json, Class<T> klass) {
    Gson gson = new Gson();
    return gson.fromJson(json, new ListOfSomething<T>(klass));
}

цель этого кода, должна использоваться внутри :List<Integer> list = new Factory<Integer>() .getFromJsonList(text, Integer.class)

List<Integer> list = new Gson().fromJson(text,
         new TypeToken<List<Integer>>(){}.getType());

Даже если техника работает и действительно очень умна (я этого не знал, и я бы никогда об этом не думал), это окончательное достижение:

TypeToken

вместо

public static final <T> List<T> getList(final Class<T[]> clazz, final String json)
{
    final T[] jsonToObject = new Gson().fromJson(json, clazz);

    return Arrays.asList(jsonToObject);
}

Для меня все это обертывание бесполезно, даже если я соглашусь с тем, что код выглядит скверно: PgetList(MyClass[].class, "[{...}]");


26
gson 2.8.0

Пример:

TypeToken#getParametized((Type rawType, Type... typeArguments))

Так как typeTokenвы можете использовать для создания , то должны сделать трюк.TypeToken.getParameterized(List.class, myType).getType(); public class GenericOf<X, Y> implements ParameterizedType { private final Class<X> container; private final Class<Y> wrapped; public GenericOf(Class<X> container, Class<Y> wrapped) { this.container = container; this.wrapped = wrapped; } public Type[] getActualTypeArguments() { return new Type[]{wrapped}; } public Type getRawType() { return container; } public Type getOwnerType() { return null; } }Type

Например:

TypeToken

6

Я сделал подход Раффаэле еще на один шаг и обобщил класс, чтобы он работал с каждым классом A, где B - непараметрированный класс. Может быть полезно для наборов и других коллекций.

Type

3

На это были ответы в предыдущих вопросах. В принципе, есть 2 варианта:

  1. Пропустите вход Typeс вызывающего сайта. Вызывающий код будет использовать TypeTokenили что-то еще для его создания.
  2. Постройте объект, Typeсоответствующий параметризованному типу самостоятельно. Это потребует от вас написать класс, который реализуетParameterizedType
Java, генерики, gson,
Похожие вопросы

Warning: fopen(../q/cache/51233910.jkhjkAAAAAAAAAAAA.html): failed to open stream: No such file or directory in /home/a0157998/domains/moredez.ru/public_html/q/index.php on line 138

Warning: fwrite() expects parameter 1 to be resource, boolean given in /home/a0157998/domains/moredez.ru/public_html/q/index.php on line 139

Warning: fclose() expects parameter 1 to be resource, boolean given in /home/a0157998/domains/moredez.ru/public_html/q/index.php on line 140