如何使用Jackson反序列化多态对象的集合

时间:2019-02-12 20:06:18

标签: java json parsing jackson polymorphism

我正在尝试反序列化来自API调用的层次化对象集合,但是我必须分析传入的JSON以确定如何进行反序列化。

我已经为对象创建了一个自定义反序列化器,并决定如何进行序列化。但是,这使我异常。

为简单起见,我将省略吸气器和吸气器

  public  abstract class Message implements Serializable {
    protected String id = UUID.randomUUID().toString();
    protected MessageType type;
    protected String to;
    protected final static long serialVersionUID = 875082919667906573L;
  } 

  public class SelectContentMessage extends Message {
    private SelectContent content;
    private final static long serialVersionUID = 875092919667906573L;
  }

public class SelectContent implements Serializable {
    private String text;
    private List<Option> options=  new ArrayList<Option>();
}

@JsonDeserialize(using = OptionDeserializer.class)
public abstract class Option implements Serializable {
    protected int index;
    protected final static long serialVersionUID = 434566339626802052L;
 }

 @JsonDeserialize(as = SimpleOption.class)
 public class SimpleOption extends Option {
     private String value = "";
     private final static long serialVersionUID = 334566339626702052L;
 }

 @JsonDeserialize(as = ComplexOption.class)
 public class ComplexOption extends Option {
     private Value value;
     private final static long serialVersionUID = 434566539626702052L;
 }

 public class Value implements Serializable {
      private String title;
 }

 public class OptionDeserializer extends JsonDeserializer<Option> {

    @Override
    public Option deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        ObjectMapper mapper = (ObjectMapper) p.getCodec();
        TreeNode node =  mapper.readTree(p);
        ObjectNode root = (ObjectNode)node;
        Class<? extends Option> instanceClass = null;
        if (root.has("value") && root.get("value").has("type")) {
            String type = root.get("value").get("type").asText();
            switch (type) {
            case "text/plain":
                instanceClass = SimpleOption.class;
            default:
                instanceClass = ComplexOption.class;
            }
            return mapper.readValue(p, instanceClass);            
        }
        instanceClass = SimpleOption.class;
        return mapper.readValue(p, instanceClass);
    }
 }   

下面是此类必须反序列化的3种JSON的示例:

{"id":"1","to":"1042221589186385@messenger.gw.msging.net","type":"application/vnd.lime.document-select+json","content":{"header":{"type":"application/vnd.lime.media-link+json","value":{"title":"Welcome to mad hatter","text":"Here we have the best hats for your head.","type":"image/jpeg","uri":"http://petersapparel.parseapp.com/img/item100-thumb.png","aspectRatio":"1:1"}},"options":[{"label":{"type":"application/vnd.lime.web-link+json","value":{"text":"Go to our site","uri":"https://petersapparel.parseapp.com/view_item?item_id=100"}}},{"label":{"type":"text/plain","value":"Show stock"},"value":{"type":"application/json","value":{"action":"show-items"}}}]}}

{"to":"553199990000@0mn.io","type":"application/vnd.lime.collection+json","content":{"itemType":"application/vnd.lime.container+json","items":[{"type":"application/vnd.lime.media-link+json","value":{"text":"Welcome to our store!","type":"image/jpeg","uri":"http://www.petshoplovers.com/wp-content/uploads/2014/03/CUIDADOS-B%C3%81SICOS-PARA-CRIAR-COELHOS.jpg"}},{"type":"application/vnd.lime.select+json","value":{"text":"Choose what you need","options":[{"order":1,"text":"See our stock"},{"order":2,"text":"Follow an order"}]}}]}}

{"id":"7577560d-5937-4115-9f82-96c0d705ea5f","type":"application/vnd.lime.select+json","content":{"text":"Choose ","scope":"immediate","options":[{"text":"App ","previewText":"App","value":"App","index":0,"type":null},{"text":"⤴️ Menu","previewText":"⤴️ Menu","value":"⤴️ Menu","index":1,"type":null}]}}

我收到以下错误:

com.fasterxml.jackson.databind.JsonMappingException: com.fasterxml.jackson.databind.node.NullNode cannot be cast to com.fasterxml.jackson.databind.node.ObjectNode (through reference chain: ai.blip.httpintegration.models.messages.SelectContentMessage["content"]->ai.blip.httpintegration.models.messages.SelectContent["options"]->java.util.ArrayList[1])

0 个答案:

没有答案