简体   繁体   English

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

[英]JSON deserialization with GSON doesn't work correctly

I'm currently writing an Android app which uses Google's GSON library for JSON deserialization. 我目前正在编写一个Android应用,该应用使用Google的GSON库进行JSON反序列化。 I already solved this (or at least a very similar) problem a while ago, but my source files got lost because stupid me made a mistake when setting up my backup process. 我已经解决了这个(或至少一个非常相似的)问题,但是我的源文件丢失了,因为愚蠢的我在设置备份过程时犯了一个错误。 Anyway, I know there's a solution. 无论如何,我知道有解决方案。 ;-) ;-)

The JSON I want to serialize comes from a web server sending data in the following form: 我要序列化的JSON来自Web服务器,它以以下形式发送数据:

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

Either error or result is always null depending on whether my request could be processed. errorresult始终为null具体取决于是否可以处理我的请求。 result can be anything from boolean to a really complex class. result可以是从boolean到非常复杂的类的任何东西。

My Java code structure looks like this: 我的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;
    }
}

When I try to deserialize a Response<Boolean> or even a Response<ArrayList<String>> everything works fine, although I was a bit confused because Response<String[]> didn't work. 当我尝试反序列化Response<Boolean>或什至Response<ArrayList<String>>一切都很好,尽管我有点困惑,因为Response<String[]>不起作用。 Even the error field is populated correctly. 甚至error字段也正确填充。 Anyway, there is one thing which is absolutely not working, it's Response<Device> where Device is a very simple class looking like this: 无论如何,有一件事是绝对不起作用的,它是Response<Device> ,其中Device是一个非常简单的类,如下所示:

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

And finally, here is my deserialization code: 最后,这是我的反序列化代码:

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

I googled for the last three hours, but I couldn't find any solution. 我搜索了过去三个小时,但找不到任何解决方案。 (Maybe it's a basic Java issue, I usually code in C#.) Can anyone help me? (也许这是一个基本的Java问题,我通常使用C#编写代码。)有人可以帮助我吗?

Edit: 编辑:

I forgot to mention that when I'm debugging my code, it seems GSON deserialized the Device JSON to an object of type LinkedTreeMap . 我忘了提一下,在调试代码时,似乎GSON将Device JSON反序列LinkedTreeMap类型的对象。 Don't know what that means, but maybe it helps you. 不知道这意味着什么,但也许可以帮到您。

The problem is likely here: 问题可能在这里:

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

Due to type erasure , T will not be resolved at runtime. 由于类型EraseT在运行时不会解析。 It will need to be up to the caller to pass in a properly reifiable type token: 它必须由调用方来传递适当可验证的类型令牌:

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

Using Guava 's version of TypeToken , things can be further abstracted: 使用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>() { });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM