Javatypes作为GSON的参数

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

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

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

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

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

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

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

UPDATE

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

 class ListOfSomething implements ParameterizedType { private Class wrapped; public ListOfSomething(Class 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 fromJsonList(String json, Class klass) { Gson gson = new Gson(); return gson.fromJson(json, new ListOfSomething(klass)); } 

即使这个技巧是有效的,而且确实非常聪明(我不知道,但我也从来没有想过),这是最后的成就:

 List list = new Factory() .getFromJsonList(text, Integer.class) 

代替

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

对我来说,即使我同意TypeToken使代码看起来很讨厌,所有这些都是无用的

 public static final  List getList(final Class 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))来创建typeToken ,那么getType()可以实现。

例如:

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

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

  public class GenericOf implements ParameterizedType { private final Class container; private final Class wrapped; public GenericOf(Class container, Class 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”解决方案,为我工作:

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

如果在kotlin中编程,我们可以在内联函数中使用reified type parameter

 class GenericGson { companion object { inline fun  Gson.fromJsonTokenType(jsonString: String): T { val type = object : TypeToken() {}.type return this.fromJson(jsonString, type) } inline fun  Gson.fromJsonType(jsonString: String): T = this.fromJson(jsonString, T::class.java) inline fun  fromJsonTokenType(jsonString: String): T = Gson().fromJsonTokenType(jsonString) inline fun  fromJsonType(jsonString: String): T = Gson().fromJsonType(jsonString) } } 

在你的代码中使用下面的代码

 val arrayList = GenericGson.fromJsonTokenType>(json)