在GSON中获取你做的对象列表
Gson gson = new Gson();
Type token = new TypeToken<List<MyType>>(){}.getType();
return gson.fromJson(json, token);
它工作得很好,但我想更进一步,让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);
遗憾地返回一个StringMaps数组,而不是类型。 T被解释为另一种泛型类型,而不是我的类型。任何解决方法?
答案 0 :(得分:42)
泛型在编译时工作。超类型令牌工作的原因是因为(匿名)内部类可以访问其通用超类(超级接口)的类型参数,而这些超类又直接存储在字节码元数据中。
编译完.java源文件后,类型参数<T>
显然会被丢弃。由于它在编译时是未知的,所以它不能存储在字节码中,因此它被删除而Gson无法读取它。
<强>更新强>
在newacct的回答之后,我试图实现他在选项2中建议的内容,即实现ParameterizedType
。代码看起来像这样(这是一个基本的test):
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
使代码看起来很讨厌,所有这些都无用,P
答案 1 :(得分:29)
从Screen
开始,您可以使用TypeToken#getParametized((Type rawType, Type... typeArguments))
创建gson 2.8.0
,然后typeToken
就可以了。
例如:
getType()
答案 2 :(得分:27)
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, "[{...}]");
答案 3 :(得分:6)
我已经采取Raffaele's方法更进一步并且对类进行了整合,因此它适用于每个类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;
}
}
答案 4 :(得分:4)
这是来自@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);
}
使用
List<MyType> myTypes = parser.fromJSonList(jsonString, MyType.class);
希望有帮助
答案 5 :(得分:3)
以前的问题已经回答了这个问题。基本上,有两个选项:
Type
。调用代码将使用TypeToken
或其他任何内容构建它。Type
。这将要求您编写一个实现ParameterizedType
答案 6 :(得分:3)
在科特林中,您可以简单地使用此功能:
inline fun <reified T> fromJson(json: String): T {
return Gson().fromJson(json, object: TypeToken<T>(){}.type)
}
并像使用它
val myTypes: List<MyType> = fromJson(jsonString);
它将解析包括gereric类型在内的任何对象作为List。关键字inline
和reified
确保不会删除该类型。
有关详细信息,我可以推荐此Medium post
答案 7 :(得分:2)
如果在kotlin中编程,我们可以在内联函数中使用reified type parameter
class GenericGson {
companion object {
inline fun <reified T : Any> Gson.fromJsonTokenType(jsonString: String): T {
val type = object : TypeToken<T>() {}.type
return this.fromJson(jsonString, type)
}
inline fun <reified T : Any> Gson.fromJsonType(jsonString: String): T = this.fromJson(jsonString, T::class.java)
inline fun <reified T : Any> fromJsonTokenType(jsonString: String): T = Gson().fromJsonTokenType(jsonString)
inline fun <reified T : Any> fromJsonType(jsonString: String): T = Gson().fromJsonType(jsonString)
}
}
在代码中使用如下所示
val arrayList = GenericGson.fromJsonTokenType<ArrayList<Person>>(json)
答案 8 :(得分:0)
Kotlin“ListOfSomething”解决方案对我有用:
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
}
}
答案 9 :(得分:0)
例如在kotlin中简单使用:
获取地点功能
fun getPlaces<T> (jsonString : String, clazz: Class<T>) : T {
val places : T = Gson().fromJson(jsonString,clazz)
return places
}
然后您可以用作:
val places = getPlaces(Array<Place>::class.java)
答案 10 :(得分:0)
public static <T> T getObject(String gsonStr) {
Gson gson = new GsonBuilder()
.setLenient()
.create();
Type collectionType = new TypeToken< T>(){}.getType();
return gson.fromJson(gsonStr,
collectionType);
}
使用时:
Class1 class1= getObject(jsonStr);
答案 11 :(得分:0)
这一切都可行。 例如具有通用键和值的地图。
CustomType type = new CustomType(Map.class, String.class, Integer.class);
因此不再有TokenType。
class CustomType implements ParameterizedType {
private final Class<?> container;
private final Class<?>[] wrapped;
@Contract(pure = true)
public CustomType(Class<?> container, Class<?>... wrapped) {
this.container = container;
this.wrapped = wrapped;
}
@Override
public Type[] getActualTypeArguments() {
return this.wrapped;
}
@Override
public Type getRawType() {
return this.container;
}
@Override
public Type getOwnerType() {
return null;
}
}
答案 12 :(得分:0)
public <T> List<T> fromJSonList(String json) {
Gson gson = new Gson();
Type collectionType = new TypeToken<List<T>>(){}.getType();
return gson.fromJson(json, collectionType);
}
//Just call
List<MyType> myTypes = parser.<MyType>fromJSonList(jsonString);