12

AFAIKは、最も柔軟なgsonのカスタマイズが可能ですTypeAdapterFactoryが、不必要に複雑になる可能性があります。処理されるクラスごとにとの両方を記述するread必要writeがありますが、実際に必要なメソッドは1つだけの場合もあります。さらに、たとえばここのようJsonSerializerに、aおよび/またはJsonDeserializerを書くのがはるかに簡単な場合もありました。これは私をこれらの質問に導きます:

  • TypeAdapterそのメソッドの1つを単に委任するaを書くことは可能ですか(例えば、の書き込みImmutableListからの書き込みへList)?
  • どういうわけJsonSerializerJsonDeserializer一緒に使用することは可能TypeAdapterFactoryですか?あるいは、彼らのための工場はありますか?
4

1 に答える 1

17

TypeAdapterそのメソッドの1つを委任するを作成することが可能です。このユースケースは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/JsonDeserializerをと組み合わせて組み合わせることができますがTypeAdapterFactory、直接行うことはできません。最も簡単な方法は、Gsonにコールバックして、クラスの子の値をシリアル化することです。この例では、内部ループを次のように変更します。

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

JsonSerializer/JsonDeserializerとの主な違いはTypeAdapter、JSONからオブジェクトモデルに移行するために必要なステージ数です。With JsonSerializer/JsonDeserializerオブジェクトは、最初にGsonのDOMモデル(JsonElementなど)に変換されてから、オブジェクトモデルに変換されます。を使用TypeAdapterすると、中間ステップがスキップされます。

これにより、タイプアダプタコードの読み取りと書き込みが少し難しくなるため、最適化されたコードにのみ使用することをお勧めします。

于 2012-09-25T15:41:08.800 に答える