2014-02-11 1 views
5

Ich möchte ein Stück JSON mit Jackson 2.x deserialisieren.Tricky (?) JSON, polymorphe Deserialisierung

Es json ist, die wie folgt aussieht:

{ 
    "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" 
       } 
      } 
     ] 
     } 
     ... 
    ] 
} 

Deshalb möchte ich Polymorphe Typ Handhabung verwenden Anhänge deserialisieren in Liste der Befestigung des. Ich habe folgende POJOs mit Mixins:

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

Erstellt Modul registrieren 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); 
    } 
} 

initialisieren ObjectMapper:

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

Wenn ich versuche, JSON deserialisieren ich folgende Ausnahme erhalten:

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

Ist es möglich, dieses JSON mit Jackson Polymorphic Type zu deserialisieren? Muss ich meine eigenen Deserializer schreiben? Kann jemand ein gutes Beispiel geben, um damit zu beginnen? Ist es überhaupt möglich, diesen JSON nur mit Anmerkungen zu analysieren?

+0

Leicht zu deserialisieren "manuell". Jackson macht es kompliziert. –

+0

Ihr geposteter Code bezieht sich nicht auf 'PageAttachmentMixin' irgendwo, ist dies die richtige Klasse? – Nachi

+0

@Nachi yep, das war ein Tippfehler, denn ich habe versucht, den Code zu vereinfachen. – vkolodrevskiy

Antwort

1

Versuchen Sie, die @JsonTypeInfo und @JsonSubTypes Annotationen auf Ihre Attachment Klasse statt auf dem Mixin zu setzen. Sie könnten sogar in der Lage sein, die Mixins vollständig zu eliminieren, indem Sie die anderen Klassen richtig kommentieren. Wenn Sie diesen Weg gehen, müssen Sie wahrscheinlich Ihre VO Klassen/Attribute und den AttachmentType mit @JsonCreator kommentieren.

Here's an article beschreibt Deserialisierung ähnlich wie Sie versuchen, zu tun. Ich habe es in der Vergangenheit nützlich gefunden, so etwas zu tun.