2012-09-25 10 views
12

AFAIK TypeAdapterFactoryによって最も柔軟なgsonのカスタマイズが可能ですが、それは不必要に複雑になる可能性があります。私はそれぞれの扱われたクラスのために、readwriteの両方を書くように強制しますが、時には1つのメソッドしか本当に必要ではありません。さらに、JsonSerializerおよび/またはJsonDeserializerが書き込む方がはるかに簡単でした。 like here。これは、これらの質問に私をリード:TypeAdapterFactoryの簡単な使用

  • TypeAdapterただけで、デリゲートメソッドの1つ(Listの書き込みにImmutableListの例えば書き込み)を記述することが可能ですか?
  • 何とかJsonSerializerおよび/またはJsonDeserializerTypeAdapterFactoryと一緒に使用できますか?あるいは、彼らのための工場はありますか?

答えて

16

メソッドの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/TypeAdapterFactoryJsonDeserializerはなく、直接に一致させることができます。最も簡単な方法は、クラス内の子値をシリアル化するためにGsonにコールバックすることです。この例では、我々はこれに内部ループを変更したい:

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

JsonSerializer/JsonDeserializerTypeAdapterの主な違いは、それはあなたのオブジェクトモデルにJSONから行くのにかかるどのように多くの段階です。 JsonSerializer/JsonDeserializerでオブジェクトは最初にGsonのDOMモデル(JsonElementなど)に変換され、オブジェクトモデルに変換されます。 TypeAdapterでは、中間ステップはスキップされます。

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

+1

これはすばらしい答えです。私はこのサイトで長年にわたって読んできた100のベストの1つです。現実的な例を提供してくれてありがとう!この答えは、私がGsonの私の見方を独り占めに変えました。 – kevinarpe

関連する問題