Converting Complex JSON with Nested Objects and Lists into POJO Classes - Notes By ShariqSP

Converting Complex JSON with Nested Objects and Lists into POJO Classes

When dealing with complex JSON structures, it is important to map them into appropriate POJO (Plain Old Java Object) classes for easy deserialization and manipulation in Java. This process involves creating a class hierarchy that reflects the JSON structure. Below, we will explain the steps and provide an example to illustrate how to handle nested objects and lists of different types of objects.

Example JSON Structure

Consider the following JSON:

Diagram: JSON to POJO Conversion

The following diagram visually represents how the complex JSON structure is converted into corresponding POJO classes:

JSON

{
                  "userId": 1,
                  "username": "shariq",
                  "profile": { ... },
                  "roles": [ ... ],
                  "settings": { ... }
                }

User (Root POJO)

                + userId: int
                + username: String
                + profile: Profile
                + roles: List
                + settings: Settings
                            

Profile

                + firstName: String
                + lastName: String
                + contactInfo: ContactInfo
                                

List<Role>

                + roleId: int
                + roleName: String
                                

Settings

                + theme: String
                + notificationsEnabled: boolean
                                

ContactInfo

                + email: String
                + phoneNumbers: List
                                

This diagram shows the following:

  • The JSON root is converted into the User class.
  • The nested objects (profile, roles, and settings) map to separate POJO classes.
  • Nested objects within Profile, such as ContactInfo, are further represented by their own POJO.
  • Lists in JSON, such as roles and phoneNumbers, map to List fields in Java.
{
              "userId": 1,
              "username": "shariq",
              "profile": {
                "firstName": "Shariq",
                "lastName": "SP",
                "contactInfo": {
                  "email": "shariq@shariqsp.com",
                  "phoneNumbers": ["1234567890", "9876543210"]
                }
              },
              "roles": [
                {"roleId": 1, "roleName": "Admin"},
                {"roleId": 2, "roleName": "Editor"}
              ],
              "settings": {
                "theme": "dark",
                "notificationsEnabled": true
              }
            }

Steps to Map JSON to POJO

  1. Analyze the JSON structure: Identify the nested objects and arrays. For each nested structure, create a corresponding POJO class.
  2. Define POJO classes: Use appropriate data types such as String, int, boolean, List<T>, or other POJO classes to represent the JSON fields.
  3. Use Jackson annotations (if needed): Annotations like @JsonProperty can be used to map JSON keys to Java field names when they do not match.
  4. Deserialize JSON to Java objects: Use Jackson's ObjectMapper to convert the JSON string into the root POJO class.

POJO Class Definitions

// Root Class
            public class User {
                private int userId;
                private String username;
                private Profile profile;
                private List<Role> roles;
                private Settings settings;
            
                // Getters and setters
            }
            
            // Nested Profile Class
            public class Profile {
                private String firstName;
                private String lastName;
                private ContactInfo contactInfo;
            
                // Getters and setters
            }
            
            // Nested ContactInfo Class
            public class ContactInfo {
                private String email;
                private List<String> phoneNumbers;
            
                // Getters and setters
            }
            
            // Role Class (for the roles array)
            public class Role {
                private int roleId;
                private String roleName;
            
                // Getters and setters
            }
            
            // Settings Class
            public class Settings {
                private String theme;
                private boolean notificationsEnabled;
            
                // Getters and setters
            }

Deserializing JSON to POJOs

To deserialize the JSON into the root User class, use the following code:

import com.fasterxml.jackson.databind.ObjectMapper;
            
            public class Main {
                public static void main(String[] args) {
                    String json = "{ \"userId\": 1, \"username\": \"shariq\", \"profile\": { ... }, \"roles\": [...], \"settings\": { ... } }"; // Full JSON here
            
                    ObjectMapper mapper = new ObjectMapper();
                    try {
                        User user = mapper.readValue(json, User.class);
                        System.out.println(user.getUsername()); // Access deserialized data
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

Key Points

  • Nesting: For every nested object in the JSON, create a corresponding Java class.
  • Lists: Use List<T> to represent JSON arrays of objects, where T is the type of object in the array.
  • Annotations: Use Jackson annotations like @JsonProperty for mapping mismatched field names or handling customization.
  • Error Handling: Ensure proper exception handling during deserialization to handle invalid or unexpected JSON structures.

Final Output

After deserialization, you can access all the nested data using getter methods of the POJO classes. For instance, to access the first phone number:

String firstPhoneNumber = user.getProfile().getContactInfo().getPhoneNumbers().get(0);
            System.out.println(firstPhoneNumber); // Output: 1234567890

This approach makes it easy to work with complex JSON data in a structured and type-safe manner.