带有泛型的Gson,ClassCastException

时间:2014-08-21 16:57:50

标签: java generics serialization gson

我有下面的代码反序列化json数组,它找不到工作。 但是,如果我尝试迭代列表,我将得到ClassCastException。 如果我用MyObj替换泛型类型T并且迭代起作用。 但我想让反序列化代码变得通用。 你能帮我解决一下这个错误吗? 提前谢谢。

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to MyObj

json反序列化代码

public static <T> List<T> mapFromJsonArray(String respInArray) {
    Type listType = new TypeToken<ArrayList<T>>(){}.getType();
    List<T> ret = new Gson().fromJson(respInArray, listType);
    return ret;
}
在for循环中出现

错误。

List<MyObj> myObjResponse = JsonUtil.<MyObj>mapFromJsonArray(jsonResponse);
for(MyObj obj : myObjResponse){ // Class cast exception 
    //do something
}

2 个答案:

答案 0 :(得分:2)

您当然需要提供mapFromJsonArray以上的更多信息 - 这是不可避免的,因为<T>对每次调用的绑定都是entirely erased at runtime。你TypeToken正在做的就是试图重新确定你没有的信息。

但是您需要做的就是传递元素类型,这将起作用:

public static <T> List<T> mapFromJsonArray(String respInArray, Class<T> elementClass) {
    Type listType = new TypeToken<List<T>>(){}
               .where(new TypeParameter<T>(){}, elementClass).getType();
    return new Gson().fromJson(respInArray, listType);
}

与你所拥有的相比,打电话不再笨拙:

List<MyObj> myObjResponse = mapFromJsonArray(jsonResponse, MyObj.class);

答案 1 :(得分:1)

TypeToken是一种在运行时获取泛型类型信息的技巧。但是通过传递一个泛型类型参数(T),由于类型擦除,你有效地做了什么:

Type listType = new TypeToken<ArrayList<Object>>(){}.getType();

这并不能为Gson提供所需的必要信息,以便正确地反序列化到列表中,因此它会不正确地进行反序列化。

一种解决方案可能是将类型标记作为参数传递给mapFromJsonArray:

public static <T> List<T> mapFromJsonArray(String respInArray, Type listType) {
    List<T> ret = new Gson().fromJson(respInArray, listType);
    return ret;
}

List<MyObj> myObjResponse = JsonUtil.<MyObj>mapFromJsonArray(
    jsonResponse, new TypeToken<ArrayList<MyObj>>(){}.getType());

for(MyObj obj : myObjResponse){
    //do something
}