1

我目前正在编写一个使用 Google 的 GSON 库进行 JSON 反序列化的 Android 应用程序。不久前我已经解决了这个(或者至少是一个非常类似的)问题,但是我的源文件丢失了,因为愚蠢的我在设置备份过程时犯了一个错误。无论如何,我知道有一个解决方案。;-)

我要序列化的 JSON 来自以以下形式发送数据的 Web 服务器:

{
    "version": "1.1",
    "error": {
        "name": "bla",
        "code": 1234,
        "message": "oops"
    },
    "result": ???
}

要么errorresult总是null取决于我的请求是否可以得到处理。result可以是任何东西,从boolean一个非常复杂的类。

我的 Java 代码结构如下所示:

public class Response<T> {

    private String version;
    private T result;
    private Error error;

    public Response() {
    }

    public boolean isError() {
        return error != null;
    }

    public String getVersion() {
        return version;
    }

    public T getResult() {
        return result;
    }
}

public class Error {

    private String name;
    private int code;
    private String message;

    public Error() {
    }

    public String getName() {
        return name;
    }

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }
}

当我尝试反序列化 aResponse<Boolean>甚至 a时Response<ArrayList<String>>,一切正常,虽然我有点困惑,因为Response<String[]>没有工作。甚至该error字段也已正确填充。无论如何,有一件事是绝对行不通的,这Response<Device>Device一个非常简单的类,如下所示:

public class Device {
    public String id;
    public String name;
    public String address;
    public String type;
}

最后,这是我的反序列化代码:

private <T> Response<T> sendCommand(/* ... */) {
    Gson gson = new Gson();

    // preparing and sending request etc.

    String responseJson = "..."; // response JSON is valid (already verified)

    Type t = new TypeToken<Response<T>>() { }.getType();
    Response<T> result = gson.fromJson(responseJson, t);
    return result;
}

private void doSomething() {
    Response<Device> response = sendCommand("getSomeDevice");
}

我用谷歌搜索了过去三个小时,但找不到任何解决方案。(也许这是一个基本的 Java 问题,我通常用 C# 编写代码。)谁能帮助我?

编辑:

我忘了提到,当我调试代码时,GSON 似乎将DeviceJSON 反序列化为 type 的对象LinkedTreeMap。不知道这意味着什么,但也许它对你有帮助。

4

1 回答 1

2

问题很可能在这里:

Type t = new TypeToken<Response<T>>() { }.getType();

由于类型擦除T在运行时不会被解析。它需要由调用者来传递一个正确的可重构类型令牌:

private <T> Response<T> sendCommand(/* ... */, TypeToken<Response<T>> type) {
    Gson gson = new Gson();

    // preparing and sending request etc.

    String responseJson = "..."; // response JSON is valid (already verified)

    Response<T> result = gson.fromJson(responseJson, type.getType());
    return result;
}

private void doSomething() {
    TypeToken<Response<T>> type = new TypeToken<Response<Device>>() { };
    Response<Device> response = sendCommand("getSomeDevice", type);
}

使用Guava的版本TypeToken,可以进一步抽象:

private <T> Response<T> sendCommand(/* ... */, TypeToken<T> responseType) {
    Gson gson = new Gson();

    // preparing and sending request etc.

    String responseJson = "..."; // response JSON is valid (already verified)

    Type type = new TypeToken<Response<T>>() { }
            .where(new TypeParameter<T>() { }, responseType)
            .getType();
    Response<T> result = gson.fromJson(responseJson, type);
    return result;
}

private void doSomething() {
    Response<Device> response =
            sendCommand("getSomeDevice", new TypeToken<Device>() { });
}
于 2013-07-02T21:51:36.973 回答