Spring Boot: Customize the Jackson ObjectMapper

Jackson is a popular JSON processing library used in Spring Boot applications for serializing and deserializing Java objects to and from JSON. The ObjectMapper is the main class in Jackson that provides functionality for reading and writing JSON. In Spring Boot, you might need to customize the default ObjectMapper to meet specific requirements, such as changing date formats, handling null values, or including custom serializers and deserializers.

In this tutorial, we will explore how to customize the Jackson ObjectMapper in a Spring Boot application.

Prerequisites

  • JDK 17 or later
  • Maven or Gradle
  • IDE (IntelliJ IDEA, Eclipse, etc.)

Step 1: Set Up a Spring Boot Project

1.1 Create a New Spring Boot Project

Use Spring Initializr to create a new project with the following dependencies:

  • Spring Web

Download and unzip the project, then open it in your IDE.

1.2 Configure application.properties

Set up the application properties for your project. This step is optional and only needed if you want to configure specific properties for your application.

# src/main/resources/application.properties

server.port=8080

Step 2: Customize the Jackson ObjectMapper

2.1 Create a Configuration Class

Create a configuration class to customize the ObjectMapper.

package com.example.demo.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonConfig {

    @Bean
    public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
        ObjectMapper objectMapper = builder.createXmlMapper(false).build();

        // Customize the ObjectMapper
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

        return objectMapper;
    }
}

Explanation:

  • @Configuration: Marks the class as a source of bean definitions.
  • Jackson2ObjectMapperBuilder: A builder provided by Spring to facilitate the creation and customization of the ObjectMapper.
  • JavaTimeModule: A module to support Java 8 Date and Time API types in Jackson.
  • SerializationFeature.WRITE_DATES_AS_TIMESTAMPS: Disables writing dates as timestamps to output ISO-8601 formatted dates instead.

2.2 Additional Customizations

You can apply additional customizations to the ObjectMapper as needed. Here are some examples:

2.2.1 Handling Null Values

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

Explanation:

  • This configuration ensures that null values are not included in the serialized JSON output.

2.2.2 Custom Serializer

Create a custom serializer for a specific type.

package com.example.demo.serializer;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

public class CustomDateSerializer extends JsonSerializer<LocalDate> {

    @Override
    public void serialize(LocalDate date, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString(date.format(DateTimeFormatter.ofPattern("dd-MM-yyyy")));
    }
}

Register the custom serializer in the ObjectMapper.

SimpleModule module = new SimpleModule();
module.addSerializer(LocalDate.class, new CustomDateSerializer());
objectMapper.registerModule(module);

Step 3: Create a Sample Model

Create a sample model class to test the customized ObjectMapper.

package com.example.demo.model;

import com.fasterxml.jackson.annotation.JsonFormat;

import java.time.LocalDate;

public class Person {

    private String name;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
    private LocalDate birthDate;

    // Getters and setters
    public String getName() {
        return name;
    }

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

    public LocalDate getBirthDate() {
        return birthDate;
    }

    public void setBirthDate(LocalDate birthDate) {
        this.birthDate = birthDate;
    }
}

Explanation:

  • The Person class has a name field and a birthDate field.
  • The @JsonFormat annotation is used to specify the format for the birthDate field.

Step 4: Create a REST Controller

Create a REST controller to test the serialization and deserialization of the Person object.

package com.example.demo.controller;

import com.example.demo.model.Person;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;

@RestController
public class PersonController {

    @GetMapping("/person")
    public Person getPerson() {
        Person person = new Person();
        person.setName("John Doe");
        person.setBirthDate(LocalDate.of(1990, 1, 1));
        return person;
    }

    @PostMapping("/person")
    public Person createPerson(@RequestBody Person person) {
        // Just echo back the received person object
        return person;
    }
}

Explanation:

  • @RestController: Marks the class as a REST controller.
  • @GetMapping("/person"): Maps GET requests to the getPerson method.
  • @PostMapping("/person"): Maps POST requests to the createPerson method.
  • @RequestBody: Indicates that the method parameter should be bound to the body of the web request.

Step 5: Running and Testing the Application

5.1 Run the Application

Run the Spring Boot application using your IDE or the command line:

./mvnw spring-boot:run

5.2 Test the Endpoints

Open your browser or use a tool like Postman to test the endpoints:

GET /person

  • URL: http://localhost:8080/person
  • Method: GET

You should see the following JSON response:

{
    "name": "John Doe",
    "birthDate": "01-01-1990"
}

POST /person

  • URL: http://localhost:8080/person
  • Method: POST
  • Body:
    {
        "name": "Jane Doe",
        "birthDate": "15-08-1995"
    }
    

You should see the following JSON response:

{
    "name": "Jane Doe",
    "birthDate": "15-08-1995"
}

Conclusion

In this tutorial, you have learned how to customize the Jackson ObjectMapper in a Spring Boot application. By creating a configuration class, you can apply various customizations such as changing date formats, handling null values, and including custom serializers. These customizations help you tailor the JSON serialization and deserialization process to meet your specific requirements.


Comments