Jackson ObjectMapper

About

ObjectMapper is a core class provided by the Jackson library, used for converting between Java objects and JSON. It allows us to:

  • Serialize Java objects to JSON

  • Deserialize JSON to Java objects

  • Work with Maps, Lists, and generic types

  • Configure inclusion/exclusion rules

  • Register modules for special data types like Java 8 date/time, Java records, etc.

Although Jackson is not a Spring-native library, Spring Boot auto-configures Jackson and provides seamless integration out-of-the-box, making ObjectMapper one of the most commonly used utilities in Spring-based applications.

Dependency

If we are using Spring Boot with web or REST modules, Jackson is included automatically via the spring-boot-starter-web dependency:

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

This transitively includes:

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
</dependency>

If we are not using Spring Boot or want to include Jackson manually, add:

Spring Integration

How Spring Boot Uses Jackson Internally ?

Spring Boot uses Jackson as the default JSON processor. When we build a REST API or web application with spring-boot-starter-web, it:

  • Automatically includes the Jackson library (jackson-databind)

  • Registers a singleton ObjectMapper bean in the Spring context

  • Uses that bean for:

    • Serializing controller response objects (@ResponseBody)

    • Deserializing request bodies into Java objects (@RequestBody)

    • JSON conversion in RestTemplate, WebClient, and Feign clients

We can inject and use this same ObjectMapper throughout our application:

Default Behavior in Spring Boot

When using Spring Boot, the default ObjectMapper is configured with sensible defaults.

Example Defaults

Feature
Default Behavior

Include null fields in JSON

Yes

Pretty-print JSON

No

Fail on unknown JSON properties

No (FAIL_ON_UNKNOWN_PROPERTIES is disabled)

Support for Java 8 Date/Time types

Yes (via jackson-datatype-jsr310)

Use of ISO-8601 for date serialization

Yes

Support for Java 8 Optional types

Yes

Snake case support

No (uses camelCase by default)

We can override these behaviors either:

  1. Through application properties

  2. By providing a custom ObjectMapper bean

Customizing ObjectMapper via application.yml

Internally, Spring Boot does this

Spring Boot binds these properties into a Jackson2ObjectMapperBuilder and applies them when initializing the ObjectMapper bean.

This is equivalent to doing this programmatically:

Overriding the Default ObjectMapper

If we need full control, define our own @Bean of type ObjectMapper. Spring Boot will use our version instead of the default.

Note: If we do this, make sure to register required modules like JavaTimeModule, otherwise date/time parsing may break.

Use Cases

1. Serialization: Java Object to JSON

Convert a Java object into a JSON string.

Write to file or output stream:

Pretty-printing:

2. Deserialization: JSON to Java Object

Convert a JSON string to a Java object.

From file:

3. Convert Between Java Objects (Object to Object Mapping)

Convert one type to another using intermediate JSON conversion. Useful for mapping DTOs to entities.

4. Convert to and from Map

POJO Class

Convert POJO to Map

Convert Map to POJO

5. Handling Collections and Generics

Deserialize a JSON array into a list of objects:

Deserialize a nested structure:

6. Deserialization with Unknown or Partial JSON

POJO Class

JSON with Extra Field (unknown)

Default Behavior (in Spring Boot)

By default, Spring Boot configures ObjectMapper to ignore unknown fields, so this will work fine.

Manually Ensuring it Ignores Unknown Fields

If we are not in Spring Boot, or just want to be sure:

Partial JSON

If price is missing, it will be set to its default value (e.g., 0.0 for double).

Serialization Inclusion Strategies

Serialization inclusion strategies determine what data gets included in the JSON output. This is important to reduce unnecessary data in API responses, especially when dealing with large objects or REST services.

Options

Strategy
Description

Include.ALWAYS

Always include the property (default)

Include.NON_NULL

Exclude null values

Include.NON_EMPTY

Exclude empty values (empty string, empty list, etc.)

Include.NON_DEFAULT

Exclude fields with default values

Include.NON_ABSENT

Exclude nulls and Java 8 Optional.empty()

Global Configuration

Field-Level Configuration

Spring Boot Configuration (application.yml)

Use Case Example

You may not want to return null or empty fields to reduce response payload size:

With NON_NULL, email will be excluded.

Date and Time Handling

Working with dates and times in Java can be tricky, especially when serializing and deserializing JSON in REST APIs. Jackson provides powerful capabilities for formatting and parsing date/time types, and Spring Boot makes this integration seamless—but only if you configure it correctly.

Why Special Handling Is Needed

Java 8 introduced a new Date-Time API under java.time.* packages like:

  • LocalDate

  • LocalDateTime

  • ZonedDateTime

  • Instant

These types are not supported natively by Jackson without additional configuration. Jackson treats them differently than older types like java.util.Date, and without proper setup, they are either:

  • Serialized as arrays (e.g. [2024, 6, 20])

  • Serialized as timestamps

  • Or cause deserialization errors

Solution

To handle Java 8 time types correctly:

  1. Register JavaTimeModule

  2. Disable writing as timestamps

This enables human-readable ISO-8601 strings like:

instead of:

Field-Level Formatting

Use @JsonFormat to define a custom date format for individual fields:

This ensures consistent formatting even if the global ObjectMapper is shared across the application.

Global Formatting in Spring Boot

Spring Boot allows configuring date/time formats centrally using application.yml or application.properties.

YAML Configuration

Effect

This:

  • Sets the format for all java.util.Date and Calendar

  • Does not apply to Java 8 java.time.* types unless you register JavaTimeModule

To apply it for both, combine Spring config + JavaTimeModule registration.

Timezone Handling

When serializing or deserializing time-zone-aware types like ZonedDateTime or OffsetDateTime, Jackson can:

  • Use default system time zone

  • Apply a specific time zone via config

  • Respect explicit time zone in the string

Set Global Time Zone

Or via Spring config:

Deserialization Considerations

When parsing strings, Jackson expects them to match the format defined by:

  • @JsonFormat (if present)

  • application.yml format (if configured)

  • ISO-8601 (default fallback for JavaTimeModule)

Mismatched formats will cause JsonParseException.

Field Naming Strategy

Field naming strategies control how Java field names are mapped to JSON keys.

Default: camelCase

snake_case:

Spring Boot Configuration

Use Case

Aligns backend field names with frontend naming conventions, especially in REST APIs.

Working with JSON Tree (JsonNode)

Use JsonNode when working with dynamic, partially known, or schema-less JSON structures.

Parsing JSON as Tree

Modifying Tree

Traversing Nested Nodes

Creating a Tree Manually

Use Case

Perfect for generic filters, form submissions, or when schema is not static.

Annotations for Fine-Grained Control

Jackson provides annotations to control serialization/deserialization behavior per class or field.

Common Annotations

Annotation
Purpose

@JsonProperty

Rename JSON property

@JsonIgnore

Exclude field

@JsonInclude

Conditional inclusion

@JsonFormat

Format dates

@JsonAlias

Accept multiple names

@JsonCreator

Constructor/factory-based deserialization

@JsonValue

Serialize enum or custom object as a value

Examples

Use Case

  • Maintain compatibility with legacy JSON.

  • Adjust naming or formatting without changing the class model.

  • Control visibility per API contract.

Working with JSON Tree (JsonNode)

Use JsonNode when working with dynamic, partially known, or schema-less JSON structures.

Parsing JSON as Tree

Modifying Tree

Traversing Nested Nodes

Creating a Tree Manually

Use Case

Perfect for generic filters, form submissions, or when schema is not static.

Exception Handling

Jackson can throw several checked and runtime exceptions during JSON processing. It’s essential to handle these gracefully, especially in REST APIs.

Common Exceptions

Exception
Cause

UnrecognizedPropertyException

JSON has fields not found in the POJO

MismatchedInputException

Type mismatch (e.g., expecting object but got array)

JsonMappingException

Problems mapping between JSON and object

JsonParseException

Malformed JSON syntax

JsonProcessingException

Parent class for all exceptions

Spring REST Exception Handler

Custom Serializers and Deserializers

In most applications, Jackson’s default serialization and deserialization behavior is sufficient. However, certain situations call for custom logic, such as:

  • Encrypting/masking sensitive data

  • Transforming legacy formats

  • Applying business rules during serialization or deserialization

  • Interacting with non-standard or inconsistent APIs

Jackson makes this easy with JsonSerializer<T> and JsonDeserializer<T> interfaces.

1. Custom Serializer

Goal: Control how a Java object or field is written to JSON.

Steps:

a) Create a serializer class:

b) Use it in our model:

Output:

2. Custom Deserializer

Goal: Control how JSON is parsed into a Java object or field.

Steps:

a) Create a deserializer class:

b) Use it in our model:

Input:

Output:

3. Apply to Entire Class

We can serialize/deserialize an entire class with custom logic if we need control beyond a field level.

Example: Serialize full object to flat string

Custom Serializer:

Use:

Output:

4. Global Registration

Instead of annotating each model field or class, we can register custom (de)serializers globally.

This affects every String field across the application. Be cautious with global registration.

5. Use with Spring Boot's Default ObjectMapper

If we don’t want to override Spring Boot’s default ObjectMapper but want to add custom behavior, use a Jackson2ObjectMapperBuilderCustomizer:

This allows customization without replacing the default Spring Boot configuration.

Last updated