Search code examples
javajsonjacksonpojo

Json to POJO parsing using jackson - @JsonPropertyOrder for below Json vary based on #students?


This is my json input

{
  "students_key": {
    "student_key_one": {
      "profile_root": "/profile/student_key_one/",
      "nickname": "sam1",
      "email": "sam1@gmail.com",
      "studentkey": "student_key_one"
    },
    "student_key_two": {
      "profile_root": "/profile/student_key_two/",
      "nickname": "sam2",
      "email": "sam2@gmail.com",
      "studentkey": "student_key_two"
    },
    "student_key_three": {
      "profile_root": "/profile/student_key_three/",
      "nickname": "sam3",
      "email": "sam3@gmail.com",
      "studentkey": "student_key_three"
    },
    "student_key_four": {
      "profile_root": "/profile/student_key_four/",
      "nickname": "sam4",
      "email": "sam4@gmail.com",
      "studentkey": "student_key_four"
    },
    "student_key_five": {
      "profile_root": "/profile/student_key_five/",
      "nickname": "sam5",
      "email": "sam5@gmail.com",
      "studentkey": "student_key_five"
    }
  }
}

As the number of students increases the properties will also increase (student_key_one, student_key_two, student_key_three, student_key_four, student_key_five, student_key_six.......) the property will dynamically increase or decrease based on #students.

As this is not an array of objects, how can I create the POJO for StudentsKey? Can someone help me write the pojo for deserialisation using jackson?


Solution

  • Breaking it down:

    The outer wrapper is an object and should be its own class

    +--------------------------+
    |                          |
    |  {                       |
    |      "students_key": {   |
    |           ...            |
    |      }                   |
    |  }                       |
    |                          |       
    +--------------------------+
    

    The { } curly brackets signifies an object, and in mapping terms, a class. And the class has only one property students_key. So we can make a class, say Students, with one field students_key

    public class Students {
        @JsonProperty("students_key")
        (???????) students;
    }
    

    What type should we make the students_key? Let's look at the structure

    "students_key": {
        "student_key_one": {
           ...
        }
        "student_key_two": {
           ...
        }
        ...
     }
    

    We should ask ourselves what data structure best supports the concept of keys/values. First thing that comes to mind is a Map. So if we made students_key a Map, the types would be

     //       (key)          (value)
     Map <    String     ,   Object    >
     //   "student_key_one": { ... }  
    

    We could go even further and give Object a solid type, since we have more attributes. So we could make a class Student

    public class Student {
        @JsonProperty("profile_root")
        private String profileRoot;
        @JsonProperty("nickname")
        private String nickname;
        @JsonProperty("email")
        private String email;
        @JsonProperty("studentkey")
        private String studentKey;
        // GETTERS and SETTERS
    
        @Override
        public String toString() {
            return "Student{" + "profileRoot=" + profileRoot + ", nickname=" 
                + nickname + ", email=" + email + ", studentKey=" + studentKey + '}';
        }
    }
    

    So out final mapping would look like

    public class Students {
        @JsonProperty("students_key")
        Map<String, Student> students;
    }
    

    When we test it out, it works as expected

    public class StudentsTest {
        public static void main(String[] args) throws Exception {
            ObjectMapper mapper = new ObjectMapper();
    
            File file = new File("test.json");
            Students students = mapper.readValue(file, Students.class);
    
            for (Student s : students.getStudents().values()) {
                System.out.println(s);
            }
        }
    }
    

    Result

    Student{profileRoot=/profile/student_key_one/, nickname=sam1, email=sam1@gmail.com, studentKey=student_key_one}
    Student{profileRoot=/profile/student_key_two/, nickname=sam2, email=sam2@gmail.com, studentKey=student_key_two}
    Student{profileRoot=/profile/student_key_three/, nickname=sam3, email=sam3@gmail.com, studentKey=student_key_three}
    Student{profileRoot=/profile/student_key_four/, nickname=sam4, email=sam4@gmail.com, studentKey=student_key_four}
    Student{profileRoot=/profile/student_key_five/, nickname=sam5, email=sam5@gmail.com, studentKey=student_key_five}