Javatypes作为GSON的参数

在GSON中获取你所做的对象列表

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

它工作的很好,但我想走得更远,并有MyType参数化,所以我可以有一个共同的function来parsing与此代码的对象的列表

 // the common function public <T> List<T> fromJSonList(String json, Class<T> type) { Gson gson = new Gson(); Type collectionType = new TypeToken<List<T>>(){}.getType(); return gson.fromJson(json, collectionType); } // the call List<MyType> myTypes = parser.fromJSonList(jsonString, MyType.class); 

可悲的是返回一个StringMaps数组,而不是types。 T被解释为另一种generics,而不是我的types。 任何解决方法?

generics在编译时工作。 超types令牌的工作原因是(匿名)内部类可以访问它们的通用超类(超接口)的types参数,而超类接口则直接存储在字节码元数据中。

一旦你的.java源文件被编译,types参数<T>显然被抛弃了。 由于在编译时不知道它,所以它不能被存储在字节码中,所以它被擦除,Gson不能读取它。

UPDATE

newacct的答案后,我试图执行他在他的选项2,即实现ParameterizedType 。 代码看起来像这样(这是一个基本的testing ):

 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; } } 

这段代码的目的是在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); } 

例:

 getList(MyClass[].class, "[{...}]"); 

Sinnce gson 2.8.0 ,你可以使用TypeToken#getParametized((Type rawType, Type... typeArguments))来创buildtypeToken ,那么getType()可以实现。

例如:

 TypeToken.getParameterized(List.class, myType).getType(); 

我已经把Raffaele的方法进一步推广了,并且使这个类生成了基因,这样它就可以与每一个类A一起工作,其中B是一个非参数化的类。 可能对集合和其他集合有用。

  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; } } 

以前的问题已经回答了。 基本上有两个选项:

  1. 从呼叫站点传入Type 。 调用代码将使用TypeToken或其他来构造它。
  2. 自己构造一个对应于参数化types的types。 这将要求您编写一个实现ParameterizedType的类

Kotlin“ListOfSomething”解决scheme,为我工作:

 fun <T: Any> getGsonList(json: String, kclass: KClass<T>) : List<T> { return getGsonInstance().fromJson<List<T>>(json, ListOfSomething<T>(kclass.java)) } internal class ListOfSomething<X>(wrapped: Class<X>) : ParameterizedType { private val wrapped: Class<*> init { this.wrapped = wrapped } override fun getActualTypeArguments(): Array<Type> { return arrayOf<Type>(wrapped) } override fun getRawType(): Type { return ArrayList::class.java } override fun getOwnerType(): Type? { return null } }