メソッドの1つを委譲するTypeAdapter
を作成することは可能です。このユースケースは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
/TypeAdapterFactory
とJsonDeserializer
はなく、直接に一致させることができます。最も簡単な方法は、クラス内の子値をシリアル化するためにGsonにコールバックすることです。この例では、我々はこれに内部ループを変更したい:
while (in.hasNext()) {
builder.add(gson.<E>fromJson(in, elementType));
}
JsonSerializer
/JsonDeserializer
とTypeAdapter
の主な違いは、それはあなたのオブジェクトモデルにJSONから行くのにかかるどのように多くの段階です。 JsonSerializer
/JsonDeserializer
でオブジェクトは最初にGsonのDOMモデル(JsonElement
など)に変換され、オブジェクトモデルに変換されます。 TypeAdapter
では、中間ステップはスキップされます。
これは、タイプアダプタコードを読み書きするのが少し難しくなるため、最適化されたコードに対してのみ使用することをお勧めします。
これはすばらしい答えです。私はこのサイトで長年にわたって読んできた100のベストの1つです。現実的な例を提供してくれてありがとう!この答えは、私がGsonの私の見方を独り占めに変えました。 – kevinarpe