简体   繁体   English

多态性如何与Gson(Retrofit)协同工作

[英]How does Polymorphism work with Gson (Retrofit)

Here is my Retrofit instance: 这是我的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);
}

Model: 模型:

class AbstractMessage {
    String id;
}

class TextMessage extends AbstractMessage {
    String textMessage;
}

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

Request: 请求:

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

Executing 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 {
            ...
        }
    });

When I execute a request I receive a collection of AbstractMessage objects. 当我执行一个请求时,我收到了一个AbstractMessage对象的集合。 The JSON can contain both text and image messages. JSON可以包含文本和图像消息。 In my case JSON converter creates AbstractMessage and maps only the id field. 在我的例子中, JSON转换器创建AbstractMessage并仅映射id字段。 How can I make converter to create TextMessage and ImageMessage objects map all matching fields and then cast it to AbstractMessage . 如何使转换器创建TextMessageImageMessage对象映射所有匹配的字段,然后将其ImageMessage转换为AbstractMessage Or there may be some other solution. 或者可能还有其他一些解决方案。

You must create a RuntimeTypeAdapterFactory for the objects AbstractMessage, TextMessage and ImageMessage and then you must set it into the gson instance. 您必须为对象AbstractMessage,TextMessage和ImageMes​​sage创建RuntimeTypeAdapterFactory ,然后必须将其设置为gson实例。

Suppose that you have those objects: 假设你有这些对象:

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;
    }
}

This below is the RuntimeTypeAdapter that you need in order to deserialize (and serialize) correctly those objects: 下面是您需要的RuntimeTypeAdapter ,以便正确地反序列化(和序列化)这些对象:

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

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

The class RuntimeTypeAdapterFactory.java is not shipped with the Gson package, so you have to download it manually. RunsonTypeAdapterFactory.java类不随Gson包一起提供,因此您必须手动下载它。

You can read more about the runtime adapter here and here 您可以在此处此处阅读有关运行时适配器的更多信息

Please note that the title of your question should be "Polymorphism with Gson" 请注意,你的问题的标题应该是“与Gson的多态性”

I hope it helps. 我希望它有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM