web-dev-qa-db-ja.com

TypeAdapterFactoryをGsonに実装するにはどうすればよいですか?

Gsonでtype TypeAdapterFactory を実装するにはどうすればよいですか?

作成の主な方法は汎用です。どうして?

登録メソッド registerTypeAdapterFactory() はタイプ引数を受け取りません。では、Gsonはどのクラスがファクトリによって処理されているかをどのようにして知るのでしょうか。

複数のクラスに1つのファクトリを実装する必要がありますか、それとも多くのクラスに1つ実装できますか?

複数のクラスに1つのファクトリを実装する場合、ドメイン外の型の引数の場合、何を返す必要がありますか?

24
Suzan Cioc

通常の型アダプター(GsonBuilder.registerTypeAdapter)を登録すると、その特定のクラスの型アダプターのみが生成されます。例えば:

public abstract class Animal { abstract void speak(); }
public class Dog extends Animal {
   private final String speech = "woof";
   public void speak() {
       System.out.println(speech);
   }
}

// in some gson related method
gsonBuilder.registerTypeAdapter(Animal.class, myTypeAdapterObject);
Gson g = gsonBuilder.create();
Dog dog = new Dog();
System.out.println(g.toJson(dog));

これを行った場合、GsonnotmyTypeAdapterObjectを使用し、Objectのデフォルトのタイプアダプターを使用します。

それでは、ANY AnimalサブクラスをJsonに変換できるタイプアダプターオブジェクトを作成するにはどうすればよいでしょうか。 TypeAdapterFactory!ファクトリは、ジェネリック型とTypeTokenクラスを使用して一致させることができます。 TypeAdapterFactoryがそのタイプのオブジェクトの処理方法を知らない場合は、nullを返す必要があります。

TypeAdapterFactoryを使用できるもう1つのことは、アダプターを他の方法でチェーン接続できないことです。デフォルトでは、GsonはGsonインスタンスをreadwriteまたはTypeAdapterメソッドに渡しません。したがって、次のようなオブジェクトがある場合:

public class MyOuterClass {
    private MyInnerClass inner;
}

TypeAdapterFactoryを使わずにTypeAdapter<MyOuterClass>の使い方を知っているTypeAdapter<MyInnerClass>を書く方法はありません。 TypeAdapterFactory.createメソッドはGsonインスタンスを渡します。これにより、TypeAdapter<MyOuterClass>MyInnerClassフィールドをシリアル化する方法を教えることができます。


一般的に、TypeAdapterFactoryの実装の記述を開始する標準的な方法は次のとおりです。

public enum FooAdapterFactory implements TypeAdapterFactory {
    INSTANCE; // Josh Bloch's Enum singleton pattern

    @SuppressWarnings("unchecked")
    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        if (!Foo.class.isAssignableFrom(type.getRawType())) return null;

        // Note: You have access to the `gson` object here; you can access other deserializers using gson.getAdapter and pass them into your constructor
        return (TypeAdapter<T>) new FooAdapter();
    }

    private static class FooAdapter extends TypeAdapter<Foo> {
        @Override
        public void write(JsonWriter out, Foo value) {
            // your code
        }

        @Override
        public Foo read(JsonReader in) throws IOException {
            // your code
        }
    }
}
42
durron597