2014-02-11 28 views
5

我想用Jackson 2.x反序列化一段JSON。Tricky(?)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" 
       } 
      } 
     ] 
     } 
     ... 
    ] 
} 

所以我想使用多态类型处理反序列化的附件 到附件的清单。 我有以下的POJOs与混入:

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

创建模块注册混入:

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吗?

+0

易于“手动”反序列化。杰克逊使其变得复杂。 –

+0

您发布的代码没有在任何地方引用'PageAttachmentMixin',这是正确的类吗? – Nachi

+0

@Nachi yep,这是一个错字,因为我试图简化代码。 – vkolodrevskiy

回答

1

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

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