2014-02-11 30 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描述的反序列化與您正在嘗試做的相似。我發現過去做這種事情很有用。