Search code examples
javaspringjacksonabstract-classjson-deserialization

How to get object of one of the abstract class implementations passed in a json object


I have a spring project wherein I have an abstract class Person as following

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({@Type(value=Employee.class, name="employee"), @Type(value = Driver.class, name = "driver")}) 
public abstract class Person {

}

I have 2 implementations of this Person class, Employee and Driver as following

@JsonTypeName("employee")
public class Employee extends Person {

 private int field1;
 private int field2;
 
 //some getters and setters
 
}

@JsonTypeName("driver")
public class Driver extends Person {

 private int field3;
 private int field4;
 private int field5;
 
 //some getters and setters
 
}

The Person object is contained in Company class as follows

public class Company {

 private String name;
 private int id;
 private Person person;// this is the object
 private int people;


}

Now, I receive the request in a json format and one of the fields is this person object as follows:

{
 "name": "some name",
 "id": 123,
 "person":{
    "type": "employee"
    "field1":"some field1 value",
    "field2":"some field2 value"
 },
 "people": 100
 
}

The thing is, the person can be either of driver or employee type. The field "type"(not present as a variable) is passed in json and the corresponding object is instantiated. However I am unable to get the hold of the instantiated object as the instantiation happens on runtime and I am not able to tell in the code which class was instantiated. And hence can't call the getters of the appropriate object(employee or driver).

Is there a way I can get the hold of the instantiated object so that I can do whatever I want with the fields of the object(field1 and field2 in case of employee and field3, field4 and field5 in case of driver), say company.getPerson().getField1();

Thanks in advance


Solution

  • If getField1() is a method of Employee and not of any Person, then no you can't do getPerson().getField1().

    And that's logic. If you're invoking getField1() on a Person, then it means that you know that this Person is an Employee and not a Driver.

    So, you should simply separate the code handling a Employee from the one handling a Driver:

    Person person = company.getPerson();
    if (person instanceof Employee) {
        Employee employee = (Employee) person;
        employee.getField1();
        //...
    } else if (person instanceof Driver) {
        Driver driver = (Driver) person;
        driver.getField3();
        //...
    }