Rod*_*sio 48 java generics gson
在GSON中获取您执行的对象列表
Gson gson = new Gson();
Type token = new TypeToken<List<MyType>>(){}.getType();
return gson.fromJson(json, token);
Run Code Online (Sandbox Code Playgroud)
它工作得很好,但我想更进一步,让MyType参数化,这样我就可以有一个通用的函数来解析这个代码的对象列表
// 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);
Run Code Online (Sandbox Code Playgroud)
遗憾地返回一个StringMaps数组,而不是类型.T被解释为另一种泛型类型,而不是我的类型.任何解决方法?
Raf*_*ele 42
泛型在编译时工作.超类型令牌工作的原因是因为(匿名)内部类可以访问其通用超类(超级接口)的类型参数,而这些超类又直接存储在字节码元数据中.
编译完.java源文件后,类型参数<T>显然会被丢弃.由于在编译时不知道它,它不能存储在字节码中,因此它被擦除而Gson无法读取它.
UPDATE
在newacct的回答之后,我尝试实现他在选项2中建议的内容,即实现a ParameterizedType.代码看起来像这样(这是一个基本的测试):
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;
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码的目的是在里面使用getFromJsonList():
public List<T> fromJsonList(String json, Class<T> klass) {
Gson gson = new Gson();
return gson.fromJson(json, new ListOfSomething<T>(klass));
}
Run Code Online (Sandbox Code Playgroud)
即使该技术有效并且确实非常聪明(我不知道它并且我从未想过它),这是最后的成就:
List<Integer> list = new Factory<Integer>()
.getFromJsonList(text, Integer.class)
Run Code Online (Sandbox Code Playgroud)
代替
List<Integer> list = new Gson().fromJson(text,
new TypeToken<List<Integer>>(){}.getType());
Run Code Online (Sandbox Code Playgroud)
对我来说,所有这些包装都没用,即使我同意TypeTokens使代码看起来很讨厌:P
old*_*god 34
既然gson 2.8.0,你可以使用TypeToken#getParametized((Type rawType, Type... typeArguments))创建typeToken,那么getType()应该做的伎俩.
例如:
TypeToken.getParameterized(List.class, myType).getType();
Run Code Online (Sandbox Code Playgroud)
kay*_*yz1 28
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);
}
Run Code Online (Sandbox Code Playgroud)
例:
getList(MyClass[].class, "[{...}]");
Run Code Online (Sandbox Code Playgroud)
我已经将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;
}
}
Run Code Online (Sandbox Code Playgroud)
这是完整的代码库,基于@oldergod的出色回答
public <T> List<T> fromJSonList(String json, Class<T> myType) {
Gson gson = new Gson();
Type collectionType = TypeToken.getParameterized(List.class, myType).getType();
return gson.fromJson(json, collectionType);
}
Run Code Online (Sandbox Code Playgroud)
使用
List<MyType> myTypes = parser.fromJSonList(jsonString, MyType.class);
Run Code Online (Sandbox Code Playgroud)
希望对你有帮助
在Kotlin 中,你可以简单地使用这个函数:
inline fun <reified T> fromJson(json: String): T {
return Gson().fromJson(json, object: TypeToken<T>(){}.type)
}
Run Code Online (Sandbox Code Playgroud)
并像使用它一样
val myTypes: List<MyType> = fromJson(jsonString);
Run Code Online (Sandbox Code Playgroud)
它将解析任何对象,包括作为列表的 gereric 类型。关键字inline并reified确保类型不会被擦除。
有关详细信息,我可以推荐此Medium 帖子