首页 > 解决方案 > 使用 JacksonXML 将对象映射到子类

问题描述

我在将 JSON 字符串对象映射到 Java 中的子类时遇到问题。我有一个Message包含 aMessageType和 aString以及消息内容的类。

public class Message {
    protected MessageType messageType;
    protected String content;

    public MessageType getMessageType() {
        return messageType;
    }

    public String getContent() {
        return content;
    }

    public void setMessageType(MessageType messageType) {
        this.messageType = messageType;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

还有一种特殊的消息,该消息包含一个额外的变量。我将此消息作为该类的子Message类:

public class QuestionMessage extends Message {

    private Question question;

    public QuestionMessage() {

    }

    public Question getQuestion() {
        return question;
    }

    public void setQuestion(Question question) {
        this.question = question;
    }
}

问题类定义为:

public class Question {
    private String question;
    private String answerA;
    private String answerB;
    private String answerC;
    private String correctAnswer;

    //Getters and setters down here.
}

在我的代码中的其他地方,我收到一个 JSON 字符串,我使用 Jackson'sObjectMapper将此字符串映射到Message类:

objectMapper.readValue(jsonString, Message.class);

现在有时 JSON 字符串是一条普通的消息,例如:

{"messageType":"NORMAL","content":"Content string"}

这个 JSON 字符串成功映射到Message类上并返回一个Message对象。但是,当我的代码收到特殊消息时,例如:

{"messageType":"NEW_QUESTION", "content":"Content String","question":{"question":"123","answerA":"123","answerB":"123","answerC":"123"}}

不幸的是,我的代码无法将后一个 json 消息映射到QuestionMessage类上。JacksonXML 是否可以映射到您提供给对象映射器的类(QuestionMessage)的子类( Message.class)?

或者这是不可能的,我是否首先必须在传入的 json 字符串中搜索“问题”节点,然后专门调用:

objectMapper.readValue(jsonString, QuestionMessage.class);

代替

objectMapper.readValue(jsonString, Message.class);

标签: javajsonjackson

解决方案


您可以自定义Deserializer检查是否存在question节点。

例如:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

import java.io.IOException;

public class MessageDeserializer extends StdDeserializer<Message> {

    public MessageDeserializer() {
        this(null);
    }

    public MessageDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public Message deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        JsonNode questionNode = node.findValue("question");

        if (questionNode != null) {
            Question questionMessage = new Question();
                ...
            return questionMessage;
        } else {
            Message message = new Message();
                ...
            return message;
        }
    }
}

并使用它:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Message.class, new MessageDeserializer());
mapper.registerModule(module);

Message readValue = mapper.readValue(json, Message.class);

在这里查看更多详情。


推荐阅读