【发布时间】:2015-05-15 14:27:27
【问题描述】:
我的 JSON 结构如下 -
{
"status": true,
"message": "Registration Complete.",
"data": {
"user": {
"username": "user88",
"email": "user@domain.com",
"created_on": "1426171225",
"last_login": null,
"active": "1",
"first_name": "User",
"last_name": "",
"company": null,
"phone": null,
"sign_up_mode": "GOOGLE_PLUS"
}
}
}
以上格式很常见。只有data键可以保存不同类型的信息,如user、product、invoice等。
我想在每个休息响应中保持 status、message 和 data 键相同。 data 将按照status 处理,message 将显示给用户。
所以基本上,所有 api 都需要上述格式。 只有data键里面的信息每次都会不同。
我已经设置了一个以下类并将其设置为 gson 转换器 - MyResponse.java
public class MyResponse<T> implements Serializable{
private boolean status ;
private String message ;
private T data;
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
Deserializer.java
class Deserializer<T> implements JsonDeserializer<T>{
@Override
public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException{
JsonElement content = je.getAsJsonObject();
// Deserialize it. You use a new instance of Gson to avoid infinite recursion to this deserializer
return new Gson().fromJson(content, type);
}
}
并使用如下 -
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
gsonBuilder.registerTypeAdapter(MyResponse.class, new Deserializer<MyResponse>());
...... ..... ....
restBuilder.setConverter(new GsonConverter(gsonBuilder.create()));
服务接口如下 -
@POST("/register")
public void test1(@Body MeUser meUser, Callback<MyResponse<MeUser>> apiResponseCallback);
@POST("/other")
public void test2(Callback<MyResponse<Product>> apiResponseCallback);
问题
我可以从回调内部访问status 和message 字段。但是 data 键中的信息不会被解析,并且像 MeUser 和 Product 这样的模型总是返回为空。
如果我将 json 结构更改为以下代码可以完美运行 -
{
"status": true,
"message": "Registration Complete.",
"data": {
"username": "user88",
"email": "user@domain.com",
"created_on": "1426171225",
"last_login": null,
"active": "1",
"first_name": "User",
"last_name": "",
"company": null,
"phone": null,
"sign_up_mode": "GOOGLE_PLUS"
}
}
如何在 data 对象中指定单独的键并成功解析它?
【问题讨论】:
-
想知道你在做什么
-
GSON 在解析时不考虑通用数据类型
private T data;。它必须是某种特定的数据类型。 -
使用这个数据类而不是
T。class DataClass { @SerializedName("user") UserClass user;// user object @SerializedName("product") ProductClass product;// product object @SerializedName("invoice") InvoiceClass invoice;// invoice object class UserClass { } class ProductClass { } class InvoiceClass { } } -
所以您总是会提前知道您是否希望 JSON 解析为
MyResponse<User>或MyResponse<Product>等?或者 Gson 是否应该自己解决这个问题 - 仅通过查看 JSON 而没有通过在 Retrofit 接口中声明具体类型来提供指导?您的 Retrofit 示例界面让我认为前者是正确的 - 在这种情况下,您可以为每个类编写(并注册!)JsonDeserializer<MyResponse<YourClass>>。 -
@Gimali 如果我理解你的话。您想在数据 f.e. 中添加新字段。用户。对吗?
标签: java android json gson retrofit