Reputation: 846
I have a class Response
which has an attribute data
.
A json file is mapped to this object. The data
attribute can be of type TaskData
or SubmitData
on the json.
If the json has the object of type TaskData
the object mapper must map to TaskData
class or should map to `SubmitData' class.
Upvotes: 0
Views: 1628
Reputation: 15388
In addition to the answer by Guillaume Polet, and if you can modify the JSON schema, this can also be done a little bit smoother using Jackson's Polymorphic (de)serialization via annotations:
@JsonTypeInfo(use=JsonTypeInfo.Id.Class, include=JsonTypeInfo.As.PROPERTY, property="@class")
class Data {}
class TaskData extends Data {}
class SubmitData extends Data {}
This will write out the full Java class name as an additional @class
property. The json needs to include the @class
property on input, however.
Instead of JsonTypeInfo.Id.Class
it is also possible to perform explicit naming
@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 {}
This will yield an additional synthetic field @dataType
, which will need to be present in the input.
If you cannot make the type explicit in the input JSON, you will need to stick to the manual approach.
Upvotes: 1
Reputation: 47608
You need to type your Response
class as follows: public class Response<T>
.
Then, when deserializing the input, provide a TypeReference
to jackson to indicate the desired type.
See this example:
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;
}
}
}
Upvotes: 0