web-dev-qa-db-ja.com

ポリモーフィズムはGson(レトロフィット)とどのように連携しますか

これが私のRetrofitインスタンスです:

@Provides
@Singleton
ApiManager provideApiManager() {
    RxJava2CallAdapterFactory rxAdapter = RxJava2CallAdapterFactory.create();

    OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .addNetworkInterceptor(new StethoInterceptor())
            .build();

    Gson gson = new GsonBuilder().create();
    GsonConverterFactory converterFactory = GsonConverterFactory.create(gson);

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(AppConstants.BASE_URL)
            .addConverterFactory(converterFactory)
            .addCallAdapterFactory(rxAdapter)
            .client(okHttpClient)
            .build();
    return retrofit.create(ApiManager.class);
}

モデル:

class AbstractMessage {
    String id;
}

class TextMessage extends AbstractMessage {
    String textMessage;
}

class ImageMessage extends AbstractMessage {
    String url;
    String text;
}

リクエスト:

@GET("direct/messages")
Observable<List<AbstractMessage>> getMessages(@Header("Authorization") String authHeader, @Body RequestObject request);   

リクエストの実行:

apiManager.getMessages(authHeader, requestObject)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Consumer<List<AbstractMessage>>() {
        @Override
        public void accept(List<AbstractMessage> messages) throws Exception {
            ...
        }
    });

リクエストを実行すると、AbstractMessageオブジェクトのコレクションを受け取ります。 JSONには、テキストメッセージと画像メッセージの両方を含めることができます。私の場合、JSONコンバーターはAbstractMessageを作成し、idフィールドのみをマップします。コンバーターを作成してTextMessageおよびImageMessageオブジェクトを作成し、一致するすべてのフィールドをマップしてからAbstractMessageにキャストするにはどうすればよいですか。または、他の解決策があるかもしれません。

19
Alex Nik

オブジェクトAbstractMessage、TextMessage、およびImageMes​​sageに対して RuntimeTypeAdapterFactory を作成してから、それをgsonインスタンスに設定する必要があります。

これらのオブジェクトがあるとします。

public class Animal {
    protected String name;
    protected String type;

    public Animal(String name, String type) {
        this.name = name;
        this.type = type;
    }
}

public class Dog extends Animal {
    private boolean playsCatch;

    public Dog(String name, boolean playsCatch) {
        super(name, "dog");
        this.playsCatch = playsCatch;
    }
}

public class Cat extends Animal {
    private boolean chasesLaser;

    public Cat(String name, boolean chasesLaser) {
        super(name, "cat");
        this.chasesLaser = chasesLaser;
    }
}

以下は、これらのオブジェクトを正しく逆シリアル化(およびシリアル化)するために必要なRuntimeTypeAdapterです。

RuntimeTypeAdapterFactory<Animal> runtimeTypeAdapterFactory = RuntimeTypeAdapterFactory
    .of(Animal.class, "type")
    .registerSubtype(Dog.class, "dog")
    .registerSubtype(Cat.class, "cat");

Gson gson = new GsonBuilder()
    .registerTypeAdapterFactory(runtimeTypeAdapterFactory)
    .create();

クラス RuntimeTypeAdapterFactory.Java はGsonパッケージに同梱されていないため、手動でダウンロードする必要があります。

ランタイムアダプタの詳細を読むことができます ここ および ここ

質問のタイトルは「Gsonによるポリモーフィズム」である必要があることに注意してください

お役に立てば幸いです。

29
db80