2014-02-11 5 views
5

Я хочу десериализовать кусок JSON, используя Jackson 2.x.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" 
       } 
      } 
     ] 
     } 
     ... 
    ] 
} 

Так что я хочу использовать полиморфный тип Handling десериализовать вложения в Список прикрепленного файла. я следующий POJO, с 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; 
} 

Создан модуль для регистрации Примеси:

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

Initialize 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"]) 

Можно ли десериализовать этот JSON с помощью полиморфного типа Jackson Поддержка обработки? Нужно ли писать собственные десериализаторы? Может ли кто-нибудь дать хороший пример ? Возможно ли вообще разобрать этот JSON, используя аннотации?

+0

Легко десериализовать «вручную». Джексон усложняет ситуацию. –

+0

Ваш размещенный код не ссылается на 'PageAttachmentMixin' в любом месте, это правильный класс? – Nachi

+0

@ Nachi yep, это была опечатка, потому что я попытался упростить код. – vkolodrevskiy

ответ

1

Попробуйте положить @JsonTypeInfo и @JsonSubTypes аннотации на ваш класс Attachment вместо того, чтобы на микшинге. Вы даже можете полностью устранить микшины, правильно отредактировав другие классы. Если вы идете по этой дороге, вам, вероятно, придется комментировать ваши классы/атрибуты VO и AttachmentType с помощью @JsonCreator.

Here's an article, который описывает десерилизацию, аналогичную тому, что вы пытаетесь сделать. Я нашел его полезным в прошлом для такого рода вещей.

Смежные вопросы