棘手(?)JSON,多态反序列化

时间:2014-02-11 01:03:57

标签: json jackson deserialization polymorphism

我想使用Jackson 2.x反序列化一块JSON。

json看起来像这样:

{
     "response":[
      230,
      {
         "id":1627,
         "from_id":4534,
         "attachments":[
            {
               "type":"audio",
               "audio":{
                  "aid":25918,
                  "owner_id":20000,
               }
            },
            {
               "type":"link",
               "link":{
                  "url":"http://lenta.ru",
                  "title":"bla"
               }
            }
         ]
      }
      ...
   ]
}

所以我想使用Polymorphic Type Handling来反序列化附件 进入附件清单。 我跟随Mixins关注POJO:

public class Post {
    private final String id;
    private List<? extends Attachment> attachments;
    // ...
}

@JsonIgnoreProperties(ignoreUnknown = true)
public class PostMixin {
    @JsonProperty("id")
    String id;

    @JsonProperty("attachments")
    List<? extends Attachment> attachments;
    // ...
}

public abstract class Attachment {
    public static enum AttachmentType {
        AUDIO, LINK
    }

    private AttachmentType type;
    public AttachmentType getType() {
        return type;
    }
}

// Not sure here if using these annotations propper way
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME,
include=JsonTypeInfo.As.PROPERTY, property = "type", visible = true)
@JsonSubTypes({
    @JsonSubTypes.Type(name="link", value=LinkAttachment.class),
    @JsonSubTypes.Type(name="audio", value=AudioAttachment.class)
})
@JsonIgnoreProperties(ignoreUnknown = true)
public class AttachmentMixin {
    @JsonProperty("type")
    @JsonDeserialize(using = AttachmentTypeDeserializer.class)
    Attachment.AttachmentType type;

    // parse type into enum
    private static class AttachmentTypeDeserializer extends
JsonDeserializer<Attachment.AttachmentType> {
        @Override
        public Attachment.AttachmentType deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
            return Attachment.AttachmentType.valueOf(jp.getText().toUpperCase());
        }
    }
}

public class LinkAttachment extends Attachment {
    private String url;
    private String title;

    public String getUrl() {
        return url;
    }
    public String getTitle() {
        return title;
    }
}

@JsonIgnoreProperties(ignoreUnknown = true)
public class LinkAttachmentMixin extends AttachmentMixin {
    @JsonProperty("url")
    String url;

    @JsonProperty("title")
    String title;
}

public class AudioAttachment extends Attachment {
    private String id;
    private String ownerId;

    public String getId() {
        return id;
    }
    public String getOwnerId() {
        return ownerId;
    }
}

@JsonIgnoreProperties(ignoreUnknown = true)
public class AudioAttachmentMixin extends AttachmentMixin {
    @JsonProperty("aid")
    private String id;

    @JsonProperty("owner_id")
    private String ownerId;
}

创建模块以注册Mixins:

public class MyModule extends SimpleModule {
    public MyModule() {
        super("MyModule");
    }

    @Override
    public void setupModule(SetupContext context) {
        context.setMixInAnnotations(Post.class, PostMixin.class);
        context.setMixInAnnotations(Attachment.class, AttachmentMixin.class);
        context.setMixInAnnotations(LinkAttachment.class, LinkAttachmentMixin.class);
        context.setMixInAnnotations(AudioAttachment.class,AudioAttachmentMixin.class);
    }
}

初始化ObjectMapper:

objectMapper = new ObjectMapper();
objectMapper.registerModule(new MyModule());

当我尝试反序列化JSON时,我得到以下异常:

java.lang.IllegalArgumentException: Class my.package.LinkAttachmentMixin is not assignable to my.package.Attachment
(through reference chain: my.package.Post["attachments"])

是否可以使用Jackson Polymorphic Type反序列化此JSON 处理支持? 我需要编写自己的反序列化器吗?有人可以给一个好人 样品开始? 是否有可能仅使用注释来解析此JSON?

1 个答案:

答案 0 :(得分:1)

尝试将@JsonTypeInfo@JsonSubTypes注释放在Attachment类而不是mixin上。您甚至可以通过正确地注释其他类来完全消除mixins。如果您走这条路,那么您可能需要使用@JsonCreator注释您的VO类/属性和AttachmentType。

Here's an article描述了与您尝试做的类似的反序列化。我发现过去做这类事情很有用。