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
ObjectMapperbean in the Spring contextUses 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
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:
Through application properties
By providing a custom
ObjectMapperbean
Customizing ObjectMapper via application.yml
application.ymlInternally, 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
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:
LocalDateLocalDateTimeZonedDateTimeInstant
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:
Register
JavaTimeModuleDisable 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.DateandCalendarDoes not apply to Java 8
java.time.*types unless you registerJavaTimeModule
To apply it for both, combine Spring config +
JavaTimeModuleregistration.
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.ymlformat (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
@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
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
Stringfield 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