使用GSON进行JSON反序列化无法正常工作

时间:2013-07-02 21:33:42

标签: java android generics gson

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

我要序列化的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;
    }
}

当我尝试反序列化Response<Boolean>甚至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");
}

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

修改

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

1 个答案:

答案 0 :(得分:2)

问题可能在这里:

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

由于type erasureT将无法在运行时解析。它需要由调用者传递一个适当的可再生类型令牌:

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);
}

使用GuavaTypeToken版本,可以进一步抽象出来:

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>() { });
}