Detailed Explanation of Jackson Serialization and Deserialization - Notes By ShariqSP

Detailed Explanation of Jackson Serialization and Deserialization

Jackson is a powerful library in Java for handling JSON data. It allows seamless conversion between Java objects and JSON strings through the processes of serialization (converting objects to JSON) and deserialization (converting JSON to objects). This section explains how to use Jackson for these operations with examples using the API from shariqsp.com.

Serialization with Jackson

Serialization is the process of converting a Java object into a JSON string. In Jackson, this is achieved using the ObjectMapper class.

Adding Jackson Dependency

To use Jackson for serialization and deserialization, you need to add the required dependency to your project. If you are using Maven as your build tool, include the following dependency in your pom.xml file:

<dependency>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-databind</artifactId>
                    <version>2.15.2</version> <!-- Use the latest version available -->
                </dependency>

If you are using Gradle, add the following to your build.gradle file:

implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2'

These dependencies include the ObjectMapper class and other utilities required for JSON serialization and deserialization with Jackson.

Classes and Methods for Serialization

  • ObjectMapper:
    • A core class in Jackson used for converting Java objects to JSON and vice versa.
    • Main method:
      • writeValueAsString(Object obj): Converts a Java object into a JSON string.

Example: Serialization

Below is an example of serializing a Java object for an API request to http://apitesting.shariqsp.com:8080/api/users/register.

import com.fasterxml.jackson.databind.ObjectMapper;
            
            class User {
                private int id;
                private String username;
                private String email;
                private String mobile;
                private String password;
            
                // Getters and setters
            }
            
            public class JacksonSerializationExample {
                public static void main(String[] args) {
                    try {
                        User user = new User();
                        user.setId(1);
                        user.setUsername("shariq");
                        user.setEmail("shariq@shariqsp.com");
                        user.setMobile("9876543210");
                        user.setPassword("securepass");
            
                        ObjectMapper objectMapper = new ObjectMapper();
                        
                        // Serialize Java object to JSON file
                        objectMapper.writeValue(new File("user.json"), user);
            
                        System.out.println("Serialized JSON saved to file: user.json");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

Output:

{
              "id": 1,
              "username": "shariq",
              "email": "shariq@shariqsp.com",
              "mobile": "9876543210",
              "password": "securepass"
            }

Deserialization with Jackson

Deserialization is the process of converting a JSON string back into a Java object. In Jackson, this is also handled by the ObjectMapper class.

Classes and Methods for Deserialization

  • ObjectMapper:
    • Main method:
      • readValue(String content, Class<T> valueType): Converts a JSON string into an instance of the specified Java class.

Example: Deserialization

Below is an example of deserializing JSON received from the API http://apitesting.shariqsp.com:8080/api/users/all.

import com.fasterxml.jackson.databind.ObjectMapper;
            
            public class JacksonDeserializationExample {
                public static void main(String[] args) {
                 
                    try {
                        ObjectMapper objectMapper = new ObjectMapper();
            
                        // Deserialize JSON file to Java object
                        User user = objectMapper.readValue(new File("user.json"), User.class);
            
                        // Print the deserialized object
                        System.out.println("Deserialized Object:");
                        System.out.println("ID: " + user.getId());
                        System.out.println("Username: " + user.getUsername());
                        System.out.println("Email: " + user.getEmail());
                        System.out.println("Mobile: " + user.getMobile());
                        System.out.println("Password: " + user.getPassword());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

Output:


            Deserialized Object:
            ID: 1
            Username: shariq
            Email: shariq@shariqsp.com
            Mobile: 9876543210
            

Key Points to Remember

  • Jackson requires a no-argument constructor in the class being serialized or deserialized.
  • Ensure proper getter and setter methods are present in the class for Jackson to access fields.
  • Annotations like @JsonIgnore, @JsonProperty, and @JsonInclude can be used for advanced configurations.
  • Jackson can handle complex nested objects and collections like lists and maps.

Understanding Jackson Annotations

Jackson is a popular library in Java for serializing and deserializing Java objects to and from JSON. It provides several annotations to customize this process. Below is an explanation of some commonly used annotations:

@JsonProperty

The @JsonProperty annotation is used to map a JSON property to a specific field or method in a Java class. This is particularly useful when the JSON key differs from the field name in the class.

                
                import com.fasterxml.jackson.annotation.JsonProperty;
            
                class Student {
                    @JsonProperty("studentId")
                    private int id;
            
                    @JsonProperty("studentName")
                    private String name;
            
                    private String password;
            
                    @JsonProperty("studentEmail")
                    private String email;
            
                    // Getters and setters...
                }
                
                

In the above example, id is serialized and deserialized as studentId, and email as studentEmail in JSON.

@JsonIgnore

The @JsonIgnore annotation is used to mark fields that should be ignored during serialization and deserialization.

                
                import com.fasterxml.jackson.annotation.JsonIgnore;
            
                class Student {
                    private int id;
                    private String name;
            
                    @JsonIgnore
                    private String password;
            
                    private String email;
            
                    // Getters and setters...
                }
                
                

In the above example, the password field will not appear in the JSON output and cannot be read from JSON.

@JsonInclude

The @JsonInclude annotation is used to include fields in the JSON only if they meet certain criteria, such as being non-null or non-default values.

                
                import com.fasterxml.jackson.annotation.JsonInclude;
            
                @JsonInclude(JsonInclude.Include.NON_NULL)
                class Student {
                    private int id;
                    private String name;
                    private String password;
                    private String email;
            
                    // Getters and setters...
                }
                
                

Here, any field with a null value will be excluded from the JSON output.

@JsonCreator

The @JsonCreator annotation is used to define a constructor or factory method for creating an object during deserialization.

                
                import com.fasterxml.jackson.annotation.JsonCreator;
                import com.fasterxml.jackson.annotation.JsonProperty;
            
                class Student {
                    private int id;
                    private String name;
            
                    @JsonCreator
                    public Student(@JsonProperty("studentId") int id, @JsonProperty("studentName") String name) {
                        this.id = id;
                        this.name = name;
                    }
            
                    // Getters and setters...
                }
                
                

@JsonIgnoreProperties

The @JsonIgnoreProperties annotation is used at the class level to ignore specified properties during serialization and deserialization.

                
                import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
            
                @JsonIgnoreProperties({"password"})
                class Student {
                    private int id;
                    private String name;
                    private String password;
                    private String email;
            
                    // Getters and setters...
                }
                
                

@JsonFormat

The @JsonFormat annotation is used to specify the format for dates and times during serialization and deserialization.

                
                import com.fasterxml.jackson.annotation.JsonFormat;
                import java.util.Date;
            
                class Student {
                    private int id;
                    private String name;
            
                    @JsonFormat(pattern = "yyyy-MM-dd")
                    private Date enrollmentDate;
            
                    // Getters and setters...
                }
                
                

@JsonSetter and @JsonGetter

These annotations can be used to customize the names of JSON properties during deserialization and serialization, respectively.

                
                import com.fasterxml.jackson.annotation.JsonGetter;
                import com.fasterxml.jackson.annotation.JsonSetter;
            
                class Student {
                    private String name;
            
                    @JsonGetter("studentName")
                    public String getName() {
                        return name;
                    }
            
                    @JsonSetter("studentName")
                    public void setName(String name) {
                        this.name = name;
                    }
                }
                
                

Example Usage

Here's how these annotations can be applied to the provided code:

                
                import java.io.File;
                import java.io.IOException;
                import com.fasterxml.jackson.annotation.*;
                import com.fasterxml.jackson.databind.ObjectMapper;
            
                @JsonInclude(JsonInclude.Include.NON_NULL)
                class Student {
                    @JsonProperty("studentId")
                    private int id;
            
                    @JsonProperty("studentName")
                    private String name;
            
                    @JsonIgnore
                    private String password;
            
                    @JsonProperty("studentEmail")
                    private String email;
            
                    public Student() {}
            
                    public Student(int id, String name, String password, String email) {
                        this.id = id;
                        this.name = name;
                        this.password = password;
                        this.email = email;
                    }
            
                    // Getters and setters...
                }
            
                public class JsonSerial {
                    public static void main(String[] args) throws IOException {
                        Student std = new Student(123, "shariq", "1234", "shariq@gmail.com");
                        ObjectMapper obj = new ObjectMapper();
            
                        // Serialize
                        obj.writeValue(new File("student.json"), std);
            
                        // Deserialize
                        Student stdOut = obj.readValue(new File("student.json"), Student.class);
                        System.out.println(stdOut);
                    }
                }