【问题标题】:GSON deserialization ignore empty objects in listGSON 反序列化忽略列表中的空对象
【发布时间】:2016-06-23 05:02:15
【问题描述】:

一个客户决定开始在数组末尾发送空的JSON 对象(以帮助他们缓存facepalm),但这在我的应用程序中引起了一大堆意外行为。

例如,这是我正在发送的数据...

[{object}, {object}, {}, {object}]

我目前使用GSON 反序列化从服务器发送的数据。我一直在研究类型适配器来过滤掉这些空对象,但是我不完全确定如何实现过滤。关于如何使用 GSON 跳过空对象的任何想法?

【问题讨论】:

  • 是实际反序列化有问题,还是解析完成并创建对象后有问题?
  • 解析是正确的......我只是想知道是否有一种方法可以轻松忽略空对象......
  • 您能否简单地迭代生成的对象项并删除缺少数据的对象项?
  • 是的,这基本上就是我最终做的事情......有点希望通过反序列化过程来做到这一点,但只是在反序列化后完成。

标签: java android json serialization gson


【解决方案1】:

我解决了这个问题...我必须创建一个TypeAdapterFactory,将空对象设置为null,然后从结果列表中过滤掉空值。

这是我的TypeAdapterFactory

private static class EmptyCheckTypeAdapterFactory implements TypeAdapterFactory {

    @Override
    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {

        // We filter out the EmptyCheckTypeAdapter as we need to check this for emptiness!
        if (Story.class.isAssignableFrom(type.getRawType())) {
            final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
            final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
            return new EmptyCheckTypeAdapter<>(delegate, elementAdapter).nullSafe();
        }
        return null;
    }

    public class EmptyCheckTypeAdapter<T> extends TypeAdapter<T> {

        private final TypeAdapter<T> delegate;
        private final TypeAdapter<JsonElement> elementAdapter;

        public EmptyCheckTypeAdapter(final TypeAdapter<T> delegate,
                                     final TypeAdapter<JsonElement> elementAdapter) {
            this.delegate = delegate;
            this.elementAdapter = elementAdapter;
        }

        @Override
        public void write(final JsonWriter out, final T value) throws IOException {
            this.delegate.write(out, value);
        }

        @Override
        public T read(final JsonReader in) throws IOException {
            final JsonObject asJsonObject = elementAdapter.read(in).getAsJsonObject();
            if (asJsonObject.entrySet().isEmpty()) {
                return null;
            }
            return this.delegate.fromJsonTree(asJsonObject);
        }
    }
}

最后,使用下面的代码过滤掉nulls

myDto.stories.removeAll(Collections.singleton(null));

【讨论】:

  • 事后过滤列表不是最佳选择,是否可以告诉 GSON 首先不要将空元素添加到列表中?
【解决方案2】:

您可以从here 尝试此解决方案

class CollectionAdapter implements JsonSerializer<Collection<?>> {

     @Override
     public JsonElement serialize(Collection<?> src, Type typeOfSrc, JsonSerializationContext context) {
     if (src == null || src.isEmpty()) // exclusion is made here
        return null;

     JsonArray array = new JsonArray();

     for (Object child : src) {
         JsonElement element = context.serialize(child);
         array.add(element);
     }

     return array;
   }
}

那就注册吧

Gson gson = new GsonBuilder().registerTypeHierarchyAdapter(Collection.class, new CollectionAdapter()).create();

【讨论】:

  • 我不需要序列化数据......我可以为反序列化做类似的事情吗?
  • 是的,这根本不是反序列化。
猜你喜欢
  • 2016-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-17
  • 1970-01-01
  • 1970-01-01
  • 2016-07-26
相关资源
最近更新 更多