【问题标题】:JsonSubTypes, list of polymorpic objects and ParcelableJsonSubTypes,多态对象列表和 Parcelable
【发布时间】:2015-07-26 14:56:45
【问题描述】:

我的 JSON 结构:

{  
     ...
     "type":"post", // Type could vary
     "items":[]     // Array of items, each item is typeOf("type") 
     ...
}  

如何在我的 POJO 中反序列化并正确打包 items 列表:

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
}

要包裹类型列表,应提供CREATOR 对象,显然,接口不能具有该对象。 我应该使用抽象类而不是接口吗?

【问题讨论】:

    标签: android json jackson


    【解决方案1】:

    好吧,因为 Jackson 期望每个列表元素都有类型信息,而我不想为此 POJO 编写自定义反序列化器 - 我用另一种方式解决了它。

    首先我做了一个接口,我的所有子类型项都必须实现。

    @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();
        // ...
    }
    

    然后我创建了一个基类,我的所有子类型项都必须扩展它。

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

    最后,我的 POJO 类:

    public class NewsFeedEnvelope {
        // ...
        @JsonProperty("rows")
        private List<FeedItem> items;
        // ...
    }
    

    现在 POJO 已成功由 Jackson 自动反序列化,无需任何自定义反序列化器。

    【讨论】:

    • 能否添加 JSON 请求示例。我有同样的疑问,我需要将子类型对象列表作为 json 数组发送。
    【解决方案2】:

    第一件事:EXTERNAL_PROPERTY 仅在值包含在另一个对象 (POJO) 中时才有效;并且不适用于Lists、数组或Maps。

    如果您使用其他包含方法之一,则应该可以将内容序列化为 JSON,并按预期读取生成的 JSON 回保留类型。也就是说,从 Java 对象开始时支持往返序列化。 除此之外,还可以支持一些 JSON 编码结构;但这取决于您尝试支持的确切结构类型。

    【讨论】:

    • 向问题添加了 json 结构。在我的情况下我应该使用什么包含方法?
    • 没有办法表示 JSON Array 的所有元素的类型; Jackson 需要每个元素的类型信息。所以为了支持这种安排,你需要编写一个自定义的反序列化器(如果你想产生这样的 JSON,还需要序列化器)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-17
    • 1970-01-01
    • 1970-01-01
    • 2013-04-10
    • 2023-03-29
    相关资源
    最近更新 更多