杰克逊基于同一类中的json映射不同的属性

时间:2015-04-10 07:25:39

标签: java jackson

我有class Response,其属性为data

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

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

2 个答案:

答案 0 :(得分:1)

除了Guillaume Polet的回答,如果你可以修改JSON模式,使用Jackson的Polymorphic (de)serialization通过注释也可以更顺畅地完成:

@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中明确显示类型,则需要坚持手动方法。

答案 1 :(得分:0)

您需要按以下方式输入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;
        }
    }

}