I have a class like:
public abstract class JsonMotivation {
protected int motivationid;
... getters and setters
public abstract String getMotivationType();
public void setMotivationType(String motivationType) {
}
}
This motivationType datafield will keep a reference
Then I have some implementing class like:
@XmlRootElement
public class JsonAntibioticMotivation extends JsonMotivation {
protected long smhid;
protected int userid;
@Override
public String getMotivationType() {
return "AB";
}
... getters and setters
}
Finally I have some more classes that extend the JsonAntibioticMotivation class e.g.
@XmlRootElement
public class JsonSwitchAntibioticMotivation extends JsonAntibioticMotivation {
@Override
public String getMotivationType() {
return "AB-S";
}
... some additional dataparameters
}
One of the classes called JsonMedicationhistory references the abstract class JsonMotivation. On deserialization I get an error saying "Can not construct instance of be.uzgent.cosara.model.json.JsonMotivation, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information"
It seems logical that Jackson does not know which concrete class to use for deserialization. Could I somehow map the motivationType to a concrete class? I've tried writing a custom deserializer and annotated JsonMotivation with @JsonDeserialize(using=JsonMotivationDeserializer.class)
public class JsonMotivationDeserializer extends JsonDeserializer<JsonMotivation> {
@Override
public JsonMotivation deserialize(JsonParser jp,
DeserializationContext ctxt) throws IOException,
JsonProcessingException {
ObjectMapper mapper= new ObjectMapper();
JsonNode node=jp.getCodec().readTree(jp);
JsonNode motivationTypeNode=node.get("motivationType");
if(motivationTypeNode!=null){
String motivationType=motivationTypeNode.textValue();
switch(motivationType){
case "AB": return mapper.readValue(jp, JsonAntibioticMotivation.class);
case "AB-N": return mapper.readValue(jp, JsonNewAntibioticMotivation.class);
case "AB-S": return mapper.readValue(jp, JsonSwitchAntibioticMotivation.class);
case "AB-E": return mapper.readValue(jp, JsonExtendAntibioticMotivation.class);
}
}
return null;
}
}
However, this did not seem to solve the problem. The ObjectMapper does not seem to know the original mappings. Is there a way to delegate the rest of the process to the original deserialization process once you know the concrete class?