1. Overview

In this article, We will learn how we can customize JSON Serialize and Deserialize in spring boot application.  @JsonComponent is annotation using that we can customize the JSON request or response.  Spring boot internally used Jackson library for Object to JSON conversion.

Let’s try to understand in which case we should require customized JSON.  In this example, We have used java.time.Instant instance so when spring converts into JSON default format it will look like:

{
    "no": 1,
    "name": "Bob",
    "designation": "Developer",
    "gender": "Male",
    "instant": {
      "epochSecond": 1532150600,
      "nano": 737000000
}

Here is “instant” is not readable as a date. We should send date to readable format. But Jackson is not providing support for all the type of object because generally it will be very based on requirements.

2. Example

In this example, We have used java.time.Instant and convert to yyyy-MM-dd HH:mm:ss readable format using @JsonComponent

spring boot custom JSON Serialize - Deserialize

spring boot custom JSON Serialize – Deserialize

2.1 pom.xml

No any other extra dependency is required because Jackson is part of spring boot.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>spring-boot-example</groupId>
    <artifactId>spring-boot-example</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <description>Spring boot custom JSON Serializers and Deserializer Example</description>
    <!-- Inherit defaults from Spring Boot -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
    </parent>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <!-- Package as an executable jar -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2.2 SpringBootConfig

Here is @Bean Module code is commented, It optional. If we do not write @JsonComponent at serialize and deserialize class then requires to register as module.

package com.javadeveloperzone;

import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.javadeveloperzone.json.DateConverter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

import java.time.Instant;


/**
 * Created by JavaDeveloperZone on 19-07-2017.
 */

@SpringBootApplication
@ComponentScan // Using a root package also allows the @ComponentScan annotation to be used without needing to specify a basePackage attribute
public class SpringBootConfig {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(SpringBootConfig.class, args);            // it wil start application
    }

    /* Require register as module if haven't write @JsonComponent in DateConverter 
    @Bean
    public Module module(){                                 // register as module
        SimpleModule module = new SimpleModule();
        module.addSerializer(Instant.class, new DateConverter.Serialize());               // register as serialize class for Instant.class
        module.addDeserializer(Instant.class, new DateConverter.Deserialize());          //  register as deserialize class for Instant.class
        return module;
    }*/
}

2.3 DateConverter

@JsonComponent annotation will register as bean or module in spring boot context so it will be used for serializing and deserializing class:

Here we have defined two static class for serializing and deserializing which extends JsonSerializer and JsonDeserializer respectively.

  • JsonSerializer has an override serialize() method where we can write our custom code for serialize.
  • JsonDeserializer has an override deserialize() method where we can write our custom code for serialize.
package com.javadeveloperzone.json;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import org.springframework.boot.jackson.JsonComponent;

@JsonComponent
public class DateConverter {

    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    private static final SimpleDateFormat sdf1 = new SimpleDateFormat(DATE_FORMAT);


    public static class Serialize extends JsonSerializer<Instant> {
        @Override
        public void serialize(Instant value, JsonGenerator jgen, SerializerProvider provider) {
            try {
                if (value == null) {
                    jgen.writeNull();
                }
                else {
                    jgen.writeString(DateTimeFormatter.ofPattern(DATE_FORMAT).withZone(ZoneId.systemDefault()).format(value) );
                }
            }catch (Exception e){
                e.printStackTrace();
            }

        }
    }

    public static class Deserialize extends JsonDeserializer<Instant> {

        @Override
        public Instant deserialize(com.fasterxml.jackson.core.JsonParser jp, DeserializationContext ctxt) throws IOException {
            try {
                String dateAsString = jp.getText();
                if (dateAsString==null) {
                    return null;
                } else {
                    return Instant.ofEpochMilli(sdf1.parse(dateAsString).getTime());
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }
}

2.4 EmployeeController

package com.javadeveloperzone.controller;

import com.javadeveloperzone.model.Employee;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
/**
 * Created by JavaDeveloperZone on 19-07-2017.
 */
@RestController
public class EmployeeController {

    @RequestMapping("/getEmployees")
    public List<Employee> getEmployees() {
        return Employee.getEmployee();
    }
}

2.6 Employee

package com.javadeveloperzone.model;
import java.io.Serializable;
import java.time.Instant;
import java.util.ArrayList;


public class Employee implements Serializable{

    private int no;
    private String name;
    private String designation;
    private String gender;
    private Instant instant = Instant.now();

    public Employee(int no, String name, String designation, String gender ) {
        this.no = no;
        this.name = name;
        this.designation = designation;
        this.gender = gender;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDesignation() {
        return designation;
    }

    public void setDesignation(String designation) {
        this.designation = designation;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Instant getInstant() {
        return instant;
    }

    public void setInstant(Instant instant) {
        this.instant = instant;
    }

    public static java.util.List<Employee> getEmployee() {
        java.util.List<Employee> employees = new ArrayList<>();
        employees.add(new Employee(1, "Bob", "Developer", "Male"));
        employees.add(new Employee(2, "Joy", "Sr. Developer", "Male"));
        employees.add(new Employee(3, "John", "CEO", "Male"));
        employees.add(new Employee(4, "Bat", "Developer", "Male"));
        employees.add(new Employee(5, "Jolly", "Developer", "Female"));
        employees.add(new Employee(6, "Bobby", "Developer", "Female"));
        return employees;
    }

}

Output:

Let call http://localhost:8282/getEmployees and check the output:

spring boot custom JSON Serialize – Deserialize

spring boot custom JSON Serialize – Deserialize

3. Conclusion

In this article, we learned about Spring boot custom JSON Serialize – Deserialize Example or we can say @JsonComponent Example with spring boot application.

4. References

5. Source Code

spring-boot-custom-json-example

 

Was this post helpful?
Let us know, if you liked the post. Only in this way, we can improve us.
Yes
No

Leave a Reply

Your email address will not be published. Required fields are marked *