My JSON structure:
{
...
"type":"post", // Type could vary
"items":[] // Array of items, each item is typeOf("type")
...
}
How can i deserialize and properly parcel items
list inside my POJO:
public class ItemsEnvelope {
private String type;
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
property = "type",
visible = true)
@JsonSubTypes({
@JsonSubTypes.Type(value = A.class, name = "A"),
@JsonSubTypes.Type(value = B.class, name = "B"),
@JsonSubTypes.Type(value = C.class, name = "C")
})
private List<Item> items;
interface Item extends Parcelable {}
class A implements Item {
// Bunch of getters/setters and Parcelable methods/constructor
}
class B implements Item {
// Bunch of getters/setters and Parcelable methods/constructor
}
class C implements Item {
// Bunch of getters/setters and Parcelable methods/constructor
}
// Bunch of getters/setters and Parcelable methods/constructor
}
To parcel typed list a CREATOR
object should be provided, which an interface, obviously, can't have.
Should i use an abstract class instead of interface?
First things first: EXTERNAL_PROPERTY
will only work when value is enclosed within another Object (POJO); and will not work for List
s, arrays or Map
s.
If you were using one of other inclusion method, things should work in that you can serialize content as JSON, and read produced JSON back retaining types as expected. That is, round-trip serialization is supported when starting with Java objects. Beyond this, some JSON encoding structures can be supported; but it depends on exact kind of structure you are trying to support.
Well, since Jackson expects type information on each list element and i didn't want to write a custom deserializer fot this POJO - i solved it another way.
First of all i did an interface which all my subtype items had to implement.
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
property = "type",
visible = true)
@JsonSubTypes({
@JsonSubTypes.Type(value = PostFeedItem.class, name = BaseFeedItem.TYPE_POST),
@JsonSubTypes.Type(value = PhotoFeedItem.class, name = BaseFeedItem.TYPE_PHOTO),
@JsonSubTypes.Type(value = AudioFeedItem.class, name = BaseFeedItem.TYPE_AUDIO),
@JsonSubTypes.Type(value = VideoFeedItem.class, name = BaseFeedItem.TYPE_VIDEO),
@JsonSubTypes.Type(value = FriendFeedItem.class, name = BaseFeedItem.TYPE_FRIEND)
})
public interface FeedItem extends Parcelable {
// ...
@BaseFeedItem.Type
String getType();
// ...
}
Then i've made a base class, which all my subtype items had to extend.
public abstract class BaseFeedItem implements FeedItem {
public static final String TYPE_POST = "post";
public static final String TYPE_COMMUNITY_POST = "group_post";
public static final String TYPE_PHOTO = "photo";
public static final String TYPE_AUDIO = "audio";
public static final String TYPE_VIDEO = "video";
public static final String TYPE_FRIEND = "friend";
@Retention(RetentionPolicy.SOURCE)
@StringDef({TYPE_POST, TYPE_COMMUNITY_POST, TYPE_PHOTO, TYPE_AUDIO, TYPE_VIDEO, TYPE_FRIEND})
public @interface Type {}
private String type;
@Type
public String getType() {
return type;
}
// ...
}
Finally, my POJO class:
public class NewsFeedEnvelope {
// ...
@JsonProperty("rows")
private List<FeedItem> items;
// ...
}
Now POJO is successfully automatically deserialized by Jackson without any custom deserializers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With