[英]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. error
或result
始终为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. 由于类型Erase ,
T
在运行时不会解析。 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: 使用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>() { });
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.