Arraylist的类型为LinkedTreeMap而不是Brewer

时间:2014-04-11 09:34:45

标签: java android gson

我正在尝试使我的响应类通用。问题是它返回一个类型为com.google.gson.internal.LinkedTreeMap而不是Brewer类型的List。

启动所有这一切的功能:

List<Brewer> brewerList = null;
try {
    Response<Brewer> responseHandler = new Response<Brewer>();
    brewerList = responseHandler.getAll(response);
    functionCallBack = Constants.FUNCTION_DB_BREWER;
    list = brewerList.toArray(new Brewer[brewerList.size()]);
} catch (IOException e) {
    Tools.LOG_ERROR(e);
}

这是我的回复课程:

public class Response<T> {

public List<T> getAll(JSONObject response) throws IOException {
    List<T> brewerList = null;

    // Map JSON to JAVA Objects
    Type listResponse = new TypeToken<ListResponse<T>>() {
    }.getType();
    ListResponse<T> responseObject = Shared.gson.fromJson(response.toString(), listResponse);

    if (responseObject != null) {
        // Status, Message, Data
        int status = responseObject.getStatus();

        Tools.LOG_DEBUG("Response - getAll, Status: " + status);

        if (responseObject.getData() != null && responseObject.getStatus() == 200) {
            brewerList = responseObject.getData();
        } else {
            Tools.LOG_DEBUG("Couldn't find the webservices!");
        }
    }
    return brewerList;
}
}

这是我从json

解析的数据类
public class ListResponse<T> {

private int status;
private List<T> data;

public ListResponse() {
}

public int getStatus() {
    return status;
}

public void setStatus(int status) {
    this.status = status;
}

public List<T> getData() {
    return data;
}

public void setData(List<T> data) {
    this.data = data;
}
}

例外:

04-11 10:54:55.994  31660-31660/be.appmax.ktsjjt E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.ArrayStoreException: source[0] of type com.google.gson.internal.LinkedTreeMap cannot be stored in destination array of type be.appmax.ktsjjt.models.Brewer[]
        at java.lang.System.arraycopy(Native Method)
        at java.util.ArrayList.toArray(ArrayList.java:523)
        at be.appmax.ktsjjt.database.SyncHandler.onRestTaskCompleted(SyncHandler.java:96)
        at be.appmax.ktsjjt.webservices.WSBrewer$1.onSuccess(WSBrewer.java:36)
        at com.loopj.android.http.JsonHttpResponseHandler$1$1.run(JsonHttpResponseHandler.java:125)
        at android.os.Handler.handleCallback(Handler.java:730)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:176)
        at android.app.ActivityThread.main(ActivityThread.java:5419)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:525)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
        at dalvik.system.NativeStart.main(Native Method)

1 个答案:

答案 0 :(得分:16)

不幸的是,由于Java中的类型擦除,您无法执行您尝试执行的操作。

进行反序列化的各种库使用的TypeToken hack试图解决这个问题,但是你不能像通常那样尝试使用泛型类型参数。 T的类型在运行时被删除,Gson无法再确定实际类型,因此它返回Map

编辑添加:解决此问题的方法是传入TypeToken而不是尝试在方法中创建它。这允许知道类型。在您的情况下,您想要返回List<T>,但TypeToken实际上是ListResponse<T>。因此,您必须使用Generics获得一些创意,并使用边界推断TypeToken类型:

public <V extends ListResponse<T>> List<T> getAll(JSONObject response, TypeToken<V> token) throws IOException {
    ...
    V responseObject = 
        Shared.gson.fromJson(response.toString(), token.getType());
    ...
}

当你打电话给你时,你需要传递TypeToken个实例,但它会起作用。

Response<Brewer> responseHandler = new Response<Brewer>();
TypeToken<ListResponse<Brewer>> token = new TypeToken<ListResponse<Brewer>>(){};
brewerList = responseHandler.getAll(response, token);