【发布时间】:2019-08-01 21:29:41
【问题描述】:
在解析来自Web Service 的响应后,我需要避免返回带有null 项的数组,但我不知道如何配置Gson 来这样做。我打算这样做,因为我不喜欢处理解析的响应(必须再次循环数组)。
让我给你看一个基本的例子来说明我的意思。
鉴于此POJO:
public class Item {
@SerializedName("_id")
private String id; // Required field
private String name;
@SerializedName("accept_ads")
private boolean acceptAds;
// Getters and setters
}
并给出来自网络服务的JSON 响应:
[
{"_id": "a01",
"name": "Test1",
"accept_ads": true},
{"name": "Test2"}
]
我创建了这个反序列化器:
public class ItemDeserializer implements JsonDeserializer<Item> {
@Override
public Item deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Item item = null;
JsonObject jsonObject = json.getAsJsonObject();
if (jsonObject.has("_id")) {
item = new Item();
item.setId(jsonObject.get("_id").getAsString());
if (jsonObject.has("name")) {
item.setName(jsonObject.get("name").getAsString());
}
if (jsonObject.has("accept_ads")) {
item.setAcceptAds(jsonObject.get("accept_ads").getAsBoolean());
}
}
return item;
}
}
然后,我创建我的 Gson 和 Retrofit 实例,如下所示:
Gson gson = new GsonBuilder().registerTypeAdapter(Item.class, new ItemDeserializer()).create();
mRetrofit = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson)).build();
不幸的是,返回的ArrayList<Item> 包含Item 和null 值。
更新
感谢@deluxe1 in the comments below,我阅读了linked SO thread,它本身并不是我想要的,因为它是关于序列化器而不是解序列化器的。但是,该线程中的另一个答案专门针对反序列化器。
很遗憾,我无法让它工作。请注意,在这种情况下,JSON HTTP 正文响应中的 JsonElements 为空,这并不是我想要实现的。在我的例子中,一个 JsonElement 可能不为空,但缺少必填字段,这最终使其无效(因此为空)。
鉴于上面的示例类,我创建了以下反序列化器:
public class NonNullListDeserializer<T> implements JsonDeserializer<List<T>> {
@Override
public List<T> deserialize(JsonElement json, Type typeOfT, JsonDeserializationcontext context) throws JsonParseException {
Gson gson = new GsonBuilder().create();
List<T> items = new ArrayList<>();
for (final JsonElement jsonElement : json.getAsJsonArray() {
T item = gson.fromJson(jsonElement, typeOfT);
if (item != null) {
items.add(item);
}
}
return items;
}
}
当然,我记得在 Gson 中注册为 TypeAdapter。
问题是,当调用该方法时,typeOfT 是 java.util.ArrayList<com.example.Item>(但为什么呢??)。结果,T item = gson.fromJson(jsonElement, typeOfT) 行没有被内部类(在本例中为 Item)调用,导致此异常:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at path $
AFAIK,类型擦除无法执行以下操作:
T item = gson.fromJson(jsonElement, T.class)
【问题讨论】:
-
您在 JSON 中缺少一个 "-char:
"a01,如果这是您真正返回的内容,您应该先修复它。 -
@vilpe89 谢谢,我已经更新了这个例子,因为这只是我这边的一个错字。另外,请注意,提供的 JSON 只是解释我的问题的一个简单示例。从 web 服务返回的 JSON 格式也很完美。
-
看看这个问题和接受的答案stackoverflow.com/a/29733208/9464051
-
@UnaDeKalamares,deluxe1 的链接对您有帮助吗?您还需要其他建议吗?
-
我正在审查那个答案,这似乎指向了正确的方向,但似乎不起作用。我将更新我的问题以包含更多信息。谢谢!