避免从改造响应向分析的数组添加空POJO对象

时间:2019-03-11 14:23:55

标签: android gson retrofit

在解析来自null的响应之后,我需要避免返回包含Web Service项的数组,但是我不知道如何配置Gson来这样做。我打算这样做,因为我不想处理解析后的响应(必须再次循环数组)。

让我向您展示我的意思的基本示例。

给出此POJO

public class Item {
  @SerializedName("_id")
  private String id;  // Required field
  private String name;
  @SerializedName("accept_ads")
  private boolean acceptAds;

  // Getters and setters
}

并收到来自Web服务的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;
  }

}

然后,我创建如下的GsonRetrofit实例:

Gson gson = new GsonBuilder().registerTypeAdapter(Item.class, new ItemDeserializer()).create();

mRetrofit = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson)).build();

不幸的是,返回的ArrayList<Item>包含一个Item和一个null值。

UPATE

感谢@deluxe1 in the comments below,我读了linked SO thread,它本身并不是我想要的,因为它是有关序列化器而不是脱盐器的。但是,该线程中的另一个答案专门针对反序列化器。

很遗憾,我无法使其正常运行。请注意,在这种情况下,关于JSON HTTP正文响应中的JsonElements为空,这并不是我要实现的目标。在我的情况下,JsonElement可能不是null,但是缺少必填字段,最终使它无效(因此为null)。

鉴于上面的示例类,我创建了以下反序列化器:

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。

问题是,调用该方法时typeOfTjava.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)

1 个答案:

答案 0 :(得分:0)

"SELECT * from issued_books where student_id= :s_id and book_name = :b_name and issue_date between :start_date and :end_date" 需要进行一些修改:

NonNullListDeserializer

现在,您需要按如下所示对class NonNullListDeserializer<T> implements JsonDeserializer<List<T>> { @Override public List<T> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { if (json instanceof JsonArray) { final JsonArray array = (JsonArray) json; final int size = array.size(); if (size == 0) { return Collections.emptyList(); } final List<T> list = new ArrayList<>(size); for (int i = 0; i < size; i++) { // get element type Type elementType = $Gson$Types.getCollectionElementType(typeOfT, List.class); T value = context.deserialize(array.get(i), elementType); if (value != null) { list.add(value); } } return list; } return Collections.emptyList(); } } 有效负载进行反序列化:

JSON