0

I have list of different objects

  List<Object> 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));

I need to make .json file from that list. Then I need to print this file with all attributes and name of object class like this:

Worker: name:John, surname:Bep, work:Farmer,salary:2500

I have done this:

public String listToJson() throws JsonProcessingException {
    List<Object> 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));

    String s = objectMapper.writeValueAsString(people);
    return s;
}

public void jsonToList() throws IOException {
    String s = listToJson();
    TypeReference<List<Object>> mapType = new TypeReference<List<Object>>() {};
    List<Object>jsonToOList= objectMapper.readValue(s,mapType);
    jsonToOList.forEach(System.out::println);
  
}

Also I have done inheritance to have List<Person> people but it returned the same.

The output now is: {name:John, surname:Bep, work:Farmer,salary:2500} without worker

Benjamin M
  • 23,599
  • 32
  • 121
  • 201
Mannualky
  • 3
  • 1
  • 4
  • You are erasing the types when you use Object class... You need `JsonTypeInfo` annotation. Similar question - https://stackoverflow.com/questions/30362446/deserialize-json-with-jackson-into-polymorphic-types-a-complete-example-is-giv – OneCricketeer Aug 20 '21 at 16:46
  • You need to tell jackson to include the class name like here: https://stackoverflow.com/questions/57725183/jackson-serialize-class-name-as-property-for-all-objects – Benjamin M Aug 20 '21 at 16:46

2 Answers2

0

If this is the answer that you are looking for;

[
  {
    "Worker": {
      "name": "John",
      "surname": "Bep",
      "work": "Farmer",
      "salary": 2500
    }
  },
  {
    "Teacher": {
      "name": "Jacob",
      "surname": "Hiu",
      "branch": "Biology",
      "classes": 2
    }
  },
  {
    "PoliceMan": {
      "name": "Zoe",
      "surname": "Clain",
      "precint": 35,
      "salary": 2800
    }
  },
  {
    "PoliceMan": {
      "name": "Joe",
      "surname": "Plain",
      "precint": 35,
      "salary": 2800
    }
  }
]

Then you can do as follows without any annotations;


    @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));

        //test
        ObjectMapper om = new ObjectMapper();

        String s = om.writeValueAsString(
                people.stream().map(
                        p-> Collections.singletonMap(p.getClass().getSimpleName(), p)
                ).collect(Collectors.toList())
        );

        System.out.println(s);
    }


    // Assuming you have such pojo classes...

    private class Person {
        String name;
        String surname;
        public Person(String name, String surname) {
            this.name = name;
            this.surname = surname;
        }
        public String getName() {
            return name;
        }
        public String getSurname() {
            return surname;
        }
    }

    private class Worker extends Person {
        String work;
        int salary;
        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;
        }
    }

    private class Teacher extends Person {
        String branch;
        int classes;
        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;
        }
    }

    private class PoliceMan extends Person {
        int precint;
        int salary;
        public PoliceMan(String name, String surname, int precint, int salary) {
            super(name, surname);
            this.precint = precint;
            this.salary = salary;
        }
        public int getPrecint() {
            return precint;
        }
        public int getSalary() {
            return salary;
        }
    }
Kemal Kaplan
  • 932
  • 8
  • 21
  • I have pojo classes. t1 method return is OK but I need to write people list to json and then read this json file and print it. I need serialize and deserialize this list. – Mannualky Aug 21 '21 at 07:41
  • Then you have to use JsonTypeInfo with full className... – Kemal Kaplan Aug 21 '21 at 14:02
0

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
    }
  }
]
Kemal Kaplan
  • 932
  • 8
  • 21
  • Now it prints Worker, Teacher,PoliceMan without its attributes – Mannualky Aug 21 '21 at 14:27
  • This may be due to versions. I am using Java 11 with fasterxml 2.12.3 and the test serializes and deserializes the array without any problems. And one more thing, if you see empty objects, it probably means that the mapper cannot find the appropriate serializer and fallbacks to UnknownSerializer. So, be sure that the JavaType's are constructed properly... – Kemal Kaplan Aug 21 '21 at 14:37