【问题标题】:Gson, ClassCastException with GenericsGson,带有泛型的 ClassCastException
【发布时间】:2014-08-21 16:57:49
【问题描述】:

我有下面的代码来反序列化 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
}

【问题讨论】:

    标签: java generics serialization gson


    【解决方案1】:

    您当然需要向mapFromJsonArray 提供比这更多的信息——这是不可避免的,因为每次调用的&lt;T&gt; 绑定都是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);
    

    【讨论】:

    • 感谢您的评论。 uinsg com.google.gson.reflect.TypeToken (Gson 2.2.4) 可以在 TypeToken 下找到。
    • @user800799:好点。我其实在这里使用的是 Guava 的 (v 17) com.google.common.reflect.TypeToken,可以用它来代替。我不确定使用纯 Gson 执行此操作的惯用方式是什么,但无论如何您可能想要/拥有 Guava,所以您可以使用它。
    【解决方案2】:

    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
    }
    

    【讨论】:

    • 非常感谢您的评论,但我更喜欢使用 Mark 的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多