If deserialization is also needed, the providing the full class name is inevitable as the following solution;
@Test
void t1() throws Exception {
// init
List<Person> people = new ArrayList<>();
people.add(new Worker("John", "Bep", "Farmer", 2500));
people.add(new Teacher("Jacob", "Hiu", 2, "Biology"));
people.add(new PoliceMan("Zoe", "Clain", 35, 2800));
people.add(new PoliceMan("Joe", "Plain", 35, 2800));
// serialize
ObjectMapper om = new ObjectMapper();
JavaType plType = om.getTypeFactory().constructCollectionLikeType(List.class, Person.class);
//serialize
String s = om.writerFor(plType).writeValueAsString(people);
System.out.println(s);
//deserialize
List<Person> p = om.readValue(s, om.getTypeFactory().constructCollectionLikeType(List.class, Person.class));
System.out.println(p.get(0).getClass().getSimpleName());
}
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.WRAPPER_OBJECT)
public static abstract class Person {
String name;
String surname;
public Person() {
}
public Person(String name, String surname) {
this.name = name;
this.surname = surname;
}
public String getName() {
return name;
}
public String getSurname() {
return surname;
}
}
public static class Worker extends Person {
String work;
int salary;
public Worker() {
super();
}
public Worker(String name, String surname, String work, int salary) {
super(name, surname);
this.work = work;
this.salary = salary;
}
public String getWork() {
return work;
}
public int getSalary() {
return salary;
}
}
public static class Teacher extends Person {
String branch;
int classes;
public Teacher() {
super();
}
public Teacher(String name, String surname, int classes, String branch) {
super(name, surname);
this.branch = branch;
this.classes = classes;
}
public String getBranch() {
return branch;
}
public int getClasses() {
return classes;
}
}
public static class PoliceMan extends Person {
int precinct;
int salary;
public PoliceMan() {
super();
}
public PoliceMan(String name, String surname, int precinct, int salary) {
super(name, surname);
this.precinct = precinct;
this.salary = salary;
}
public int getPrecinct() {
return precinct;
}
public int getSalary() {
return salary;
}
}
The output is as follows;
[
{
"some.package.name$Worker": {
"name": "John",
"surname": "Bep",
"work": "Farmer",
"salary": 2500
}
},
{
"some.package.name$Teacher": {
"name": "Jacob",
"surname": "Hiu",
"branch": "Biology",
"classes": 2
}
},
{
"some.package.name$PoliceMan": {
"name": "Zoe",
"surname": "Clain",
"precinct": 35,
"salary": 2800
}
},
{
"some.package.name$PoliceMan": {
"name": "Joe",
"surname": "Plain",
"precinct": 35,
"salary": 2800
}
}
]