12

AFAIK 可以通过 AFAIK 进行最灵活的 gson 定制TypeAdapterFactory,但它可能会变得不必要地复杂。它迫使我为每个处理的类都编写readwrite,而有时只需要一种方法。此外,有时 aJsonSerializer和/或JsonDeserializer更容易编写,例如这里。这让我想到了这些问题:

  • 是否有可能编写一个TypeAdapter简单地委托其方法之一的a(例如,ImmutableList从写到写List)?
  • 是否可以以某种方式使用JsonSerializer和/或JsonDeserializerTypeAdapterFactory? 或者,有适合他们的工厂吗?
4

1 回答 1

17

可以创建一个TypeAdapter委托其方法之一的 a。这个用例是 API 的重要组成部分,有一个getDelegateAdapter()方法就是为了这个目的。this作为第一个参数传递,getDelegateAdapter它将返回在当前工厂之后优先的适配器。

TypeAdapterFactory immutableListFactory = new TypeAdapterFactory() {
  @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
    if (!(type.getType() instanceof ParameterizedType)
        || !type.getRawType().equals(ImmutableList.class)) {
      return null;
    }

    ParameterizedType parameterizedType = (ParameterizedType) type.getType();
    TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
    TypeAdapter<?> elementAdapter = gson.getAdapter(
        TypeToken.get(parameterizedType.getActualTypeArguments()[0]));
    return new ImmutableListAdapter(delegate, elementAdapter);
  }

  class ImmutableListAdapter<E> extends TypeAdapter<ImmutableList<E>> {
    private TypeAdapter<List<E>> delegate;
    private TypeAdapter<E> element;

    ImmutableListAdapter(TypeAdapter<List<E>> delegate, TypeAdapter<E> element) {
      this.delegate = delegate;
      this.element = element;
    }

    @Override public void write(JsonWriter out, ImmutableList<E> value) throws IOException {
      delegate.write(out, value);
    }

    @Override public ImmutableList<E> read(JsonReader in) throws IOException {
      if (in.peek() == JsonToken.NULL) {
        in.nextNull();
        return null;
      }
      ImmutableList.Builder<E> builder = ImmutableList.builder();
      in.beginArray();
      while (in.hasNext()) {
        builder.add(element.read(in));
      }
      in.endArray();
      return builder.build();
    }
  }
};

您可以混合和匹配JsonSerializer/JsonDeserializerTypeAdapterFactory,但不能直接。最简单的方法是回调 Gson 以序列化类中的子值。在此示例中,我们将内部循环更改为:

      while (in.hasNext()) {
        builder.add(gson.<E>fromJson(in, elementType));
      }

JsonSerializer/JsonDeserializer和之间的主要区别在于TypeAdapter从 JSON 到您的对象模型需要多少个阶段。用JsonSerializer/JsonDeserializer对象首先转换为 Gson 的 DOM 模型(JsonElement等),然后再转换为你的对象模型。使用TypeAdapter,跳过中间步骤。

这使得类型适配器代码的读写变得有点棘手,因此您应该只将它用于优化代码。

于 2012-09-25T15:41:08.800 回答