【问题标题】:JSON deserialization with GSON doesn't work correctly使用 GSON 的 JSON 反序列化无法正常工作
【发布时间】:2013-07-02 21:33:41
【问题描述】:

我目前正在编写一个使用 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;
    }
}

当我尝试反序列化 Response&lt;Boolean&gt; 甚至 Response&lt;ArrayList&lt;String&gt;&gt; 时,一切正常,尽管我有点困惑,因为 Response&lt;String[]&gt; 不起作用。甚至error 字段也被正确填充。无论如何,有一件事绝对不起作用,它是Response&lt;Device&gt;,其中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 似乎将Device JSON 反序列化为LinkedTreeMap 类型的对象。不知道这是什么意思,但也许对你有帮助。

【问题讨论】:

    标签: java android generics gson


    【解决方案1】:

    问题可能出在这里:

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

    【讨论】:

    • 我使用 Guava 库使用了您的第二种方法 - 就像一个魅力。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多