Как десериализовать коллекцию полиморфных объектов с помощью Джексона - PullRequest
0 голосов
/ 12 февраля 2019

Я пытаюсь десериализовать коллекцию объектов, которые являются иерархическими и происходят из вызова 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])
...