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; } }
以前的问题已经回答了。 基本上有两个选项:
- 从呼叫站点传入
Type
。 调用代码将使用TypeToken
或其他来构造它。 - 自己构造一个对应于参数化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)