我正在从Asynctask + Loader迁移到Retrofit以获取核心网络。直到我遇到以前没有发生过ClassCastExceptions的情况一直很顺利:
ImagePojo imagePojo = (ImagePojo) mediaPojo; // Error: cannot cast MediaPojo to ImagePojo
这是我在层次结构中的POJO的骨架:
public class MediaPojo extends CustomObservable implements Parcelable {
@SerializedName("media_id")
private String mMid;
@SerializedName("type")
private String mType;
@SerializedName("title")
public MediaPojo() {
}
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mNid);
dest.writeString(mType);
dest.writeString(mTitle);
}
public static final Parcelable.Creator<MediaPojo> CREATOR = new Parcelable.Creator<MediaPojo>() {
@Override
public MediaPojo createFromParcel(Parcel source) {
return new MediaPojo(source);
}
@Override
public MediaPojo[] newArray(int size) {
return new MediaPojo[size];
}
};
...
}
//定义所有媒体类型共有的字段
public class VideoPojo extends MediaPojo implements Parcelable {
@SerializedName("video_id")
private String mVid;
@SerializedName("video_url")
private String mVideoUrl;
@SerializedName("thumbnail")
private String mThumbnail ...
}
public class ImagePojo extends MediaPojo implements Parcelable {
@SerializedName("image_url")
private String mImageUrl;
@SerializedName("width")
private String mImageWidth;
@SerializedName("height")
private String mImageHeight
...
}
//其他类型:TextPojo,InfoGraphicPojo ...
到目前为止,我在迁移中对POJO所做的唯一更改是添加@SerializedName注释以允许Retrofit自动将JSON字段映射到定义的POJO实例变量。我发现有必要在运行时将通用MediaPojo转换为特定类型的POJO转换,因为我对api.mydomain.com/media的REST调用可以返回代表各种媒体(视频,图像等)的JSON。
有没有办法让Retrofit围绕我现有的对象继承结构工作?或者我可以用Parcelable接口进行序列化吗?
答案 0 :(得分:2)
是的,问题是gson总是在改装调用中创建类型。您需要提供custom deserializer以根据您的type
字段确定对象类型。这是一个可能看起来像的草图。
public class ModiaPojoDeserializer implements JsonDeserializer<Model> {
private static final String TYPE_FIELD = "type";
private static final String IMAGE_TYPE = "image";
private static final String VIDEO_TYPE = "video";
@Override
public Model deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonObject() && json.getAsJsonObject().has(TYPE_FIELD)) {
JsonObject jsonObject = json.getAsJsonObject();
final String type = jsonObject.get(TYPE_FIELD).getAsString();
if (VIDEO_TYPE.equals(type)) {
return context.deserialize(json, VideoPojo.class);
} else if (IMAGE_TYPE.equals(type)) {
return context.deserialize(json, ImagePojo.class);
} // ...
// If you need to deserialize as MediaPojo,
// deserialize without the current context
// or you will infinite loop
return new Gson().fromJson(json, typeOfT);
} else {
// Return a blank object on error, could use null
return new MediaPojo();
}
}
}
然后,您将使用自定义反序列化器使用Gson.Builder
创建自定义gson对象 -
Gson gson = new GsonBuilder()
.registerTypeAdapter(MediaPojo.class, new MediaPojoDeserializer())
.create();
然后在创建RestAdapter
-
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.mydomain.com")
.setConverter(new GsonConverter(gson))
.build();