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