I want to use Jackson to dynamically deserialize objects into the appropriate java classes, but I'm having trouble configuring Jackson the right way.
I have the following simplified model (getters/setters omitted for brevity):
class GeneralObject {
public String objType;
public String commonProp;
public GeneralObject nestedObject;
// map for additional properties, so that I can re-serialize the full object later
public Map<String, JsonNode> additionalFields = new HashMap<>();
@JsonAnyGetter
public Map<String, JsonNode> getAdditionalFields() {
return additionalFields;
}
@JsonAnySetter
public void addAdditionalField(String fieldName, JsonNode value) {
this.additionalFields.put(fieldName, value);
}
}
class SpecialObject extends GeneralObject {
public String specialProp;
}
In reality, there are different kinds of "special Objects", and I want to be able to add more in the future, when the need comes.
The jsons look like this (I get them from external sources, I cannot change the format in which they are sent):
{
"objType": "someType1",
"commonProp": "example1..."
}
{
"objType": "SPECIAL",
"commonProp": "example2...",
"specialProp": "more example"
}
{
"objType": "someOtherType",
"commonProp": "example3...",
"nestedObject": {
"objType": "SPECIAL",
"commonProp": "example2...",
"specialProp": "more example"
}
}
I am currently parsing them like this:
ObjectMapper mapper = new ObjectMapper();
String objString = "{\"objType\": \"SPECIAL\", \"commonProp\": \"...\", \"specialProp\": \"more example\"}";
GeneralObject genObj = mapper.readValue(objString, GeneralObject.class);
if (genObj.objType.equals("SPECIAL")) {
genObj = mapper.readValue(objString, SpecialObject.class);
}
// Some business-logic: If SPECIAL, then this cast is required to work:
System.out.println(((SpecialObject) genObj).specialProp);
This works for the top-level object, but not for the nested objects. If, for example, the nested Object is a SPECIAL object, it will still be deserialized as a common object.
What I want do do is to tell Jackson: "No matter the nesting-level, if objType=SPECIAL, use SpecialObject, else use GeneralObject". I looked into Polymorphic Deserialization and tried using @JsonSubTypes, but could not set up this logic correctly. How can I make sure that SPECIAL objects are deserialized into the appropriate class, even if they are nested?