Jackson在同一类中基于json映射不同的属性



我有一个class Response,它有一个属性data

一个json文件被映射到这个对象。json上的data属性可以是TaskDataSubmitData类型。

如果json具有类型为TaskData的对象,则对象映射器必须映射到TaskData类,或者应该映射到"SubmitData"类。

除了Guillaume Polet的答案,如果您可以修改JSON模式,还可以通过注释使用Jackson的Polymorphic(de)序列化来更顺利地完成:

@JsonTypeInfo(use=JsonTypeInfo.Id.Class, include=JsonTypeInfo.As.PROPERTY, property="@class")
class Data {}
class TaskData extends Data {}
class SubmitData extends Data {}

这将写出完整的Java类名作为一个额外的@class属性。然而,json需要在输入中包含@class属性。

代替JsonTypeInfo.Id.Class,也可以执行显式命名

@JsonTypeInfo(use=JsonTypeInfo.Id.Class, include=JsonTypeInfo.As.PROPERTY, property="@dataType")
@JsonSubTypes({
    JsonSubTypes.Type(value=TaskData.class, name="task"),
    JsonSubTypes.Type(value=SubmitData.class, name="submit")
})
class Data {}
@JsonTypeName("task")
class TaskData extends Data {}
@JsonTypeName("submit")
class SubmitData extends Data {}

这将产生额外的合成字段@dataType,该字段将需要存在于输入中。

如果不能在输入JSON中显式显示类型,则需要坚持手动方法

您需要按如下方式键入Response类:public class Response<T>

然后,当反序列化输入时,向jackson提供TypeReference以指示所需的类型。

参见此示例:

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class TestJacksonTyping {
    public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException {
        ObjectMapper mapper = new ObjectMapper();
        Response<TaskData> taskResponse = new Response<TaskData>();
        TaskData taskData = new TaskData();
        taskData.setTaskTitle("Some title");
        taskResponse.setData(taskData);
        Response<SubmitData> submitResponse = new Response<SubmitData>();
        SubmitData submitData = new SubmitData();
        submitData.setSubmitValue(256);
        submitResponse.setData(submitData);
        StringWriter sw = new StringWriter();
        mapper.writeValue(sw, taskResponse);
        String taskResponseJson = sw.toString();
        mapper.writeValue(sw = new StringWriter(), submitResponse);
        String submitResponseJson = sw.toString();
        Response<TaskData> deserializedTaskResponse = mapper.reader(new TypeReference<Response<TaskData>>() {
        }).readValue(new StringReader(taskResponseJson));
        Response<SubmitData> deserializedSubmitResponse = mapper.reader(new TypeReference<Response<SubmitData>>() {
        }).readValue(new StringReader(submitResponseJson));
        System.out.println(deserializedTaskResponse.getData().getTaskTitle());
        System.out.println(deserializedSubmitResponse.getData().getSubmitValue());
    }
    public static class Response<T> {
        private T data;
        public T getData() {
            return data;
        }
        public void setData(T data) {
            this.data = data;
        }
    }
    public static class TaskData {
        private String taskTitle;
        public String getTaskTitle() {
            return taskTitle;
        }
        public void setTaskTitle(String taskTitle) {
            this.taskTitle = taskTitle;
        }
    }
    public static class SubmitData {
        private int submitValue;
        public int getSubmitValue() {
            return submitValue;
        }
        public void setSubmitValue(int submitValue) {
            this.submitValue = submitValue;
        }
    }
}

最新更新