Spring Boot 4.1 Upgrade: Why Your Decade-Old ObjectMapper Breaks First

This article details the practical challenges and solutions when migrating from Spring Boot 3.x to 4.x, focusing on the Jackson 2 to 3 transition including package changes, exception handling updates, annotation exceptions, immutable ObjectMapper configuration, and coexistence strategies for legacy dependencies.

LuTiao Programming
LuTiao Programming
LuTiao Programming
Spring Boot 4.1 Upgrade: Why Your Decade-Old ObjectMapper Breaks First

Upgrading a Spring Boot 3.x project to 4.x revealed that the first compilation errors came not from Spring Security or Hibernate, but from the long-used ObjectMapper and Jackson2ObjectMapperBuilderCustomizer. Spring Boot 4 defaults to Jackson 3, which changes both Maven GroupId (from com.fasterxml.jackson to tools.jackson) and Java package names.

Don't Rush Global Package Replacement

A typical event serialization class using com.fasterxml.jackson.databind.ObjectMapper and catching JsonProcessingException must be updated. Jackson 3 moves ObjectMapper to tools.jackson.databind.ObjectMapper, but the author recommends switching to the more specific JsonMapper (from tools.jackson.databind.json.JsonMapper) for JSON-only use cases.

Exception handling also changes: JsonProcessingException becomes JacksonException (in tools.jackson.core), and the exception hierarchy no longer inherits from IOException — it's now a RuntimeException. This means many try/catch blocks that only wrapped to satisfy checked-exception requirements can be removed, though explicit catching of JacksonException remains possible for business logic like dead-letter handling.

Annotations: The Package Exception

A critical trap: jackson-annotations stays in com.fasterxml.jackson.annotation. Annotations like @JsonProperty, @JsonIgnore, @JsonCreator, @JsonInclude do not move. However, databind annotations like @JsonSerialize and @JsonDeserialize do move to tools.jackson.databind.annotation. A global replace of com.fasterxml.jacksontools.jackson would break annotation imports. The author advises letting Maven resolve dependencies first, then fixing imports via IDE compilation errors.

ObjectMapper Configuration: Immutable Builder Pattern

Old custom ObjectMapper beans using mutable setters ( setSerializationInclusion, disable, registerModule) must adapt. Jackson 3 makes ObjectMapper immutable; configuration is done via builders. For standalone use:

import com.fasterxml.jackson.annotation.JsonInclude;
import tools.jackson.databind.json.JsonMapper;

JsonMapper jsonMapper = JsonMapper.builder()
    .changeDefaultPropertyInclusion(inclusion ->
        inclusion.withValueInclusion(JsonInclude.Include.NON_NULL))
    .build();

Within Spring Boot, prefer configuration properties over custom beans:

spring:
  jackson:
    default-property-inclusion: non_null

For code-level customization, use the new JsonMapperBuilderCustomizer (replacing Jackson2ObjectMapperBuilderCustomizer):

import org.springframework.boot.jackson.autoconfigure.JsonMapperBuilderCustomizer;
import tools.jackson.databind.SerializationFeature;

@Configuration
public class JacksonConfig {
    @Bean
    JsonMapperBuilderCustomizer jsonMapperCustomizer() {
        return builder -> builder.disable(SerializationFeature.INDENT_OUTPUT);
    }
}

The author removed the custom ObjectMapper bean entirely, noting that most projects only needed null handling, date format, timezone, enum behavior, unknown fields, and property naming — all configurable via properties. Defining a custom JsonMapper bean replaces auto-configuration and can drop Spring Boot's registered modules and converters.

JavaTimeModule Integrated

Jackson 3 bundles formerly separate modules ( jackson-module-parameter-names, jackson-datatype-jdk8, jackson-datatype-jsr310) into databind. The dependency com.fasterxml.jackson.datatype:jackson-datatype-jsr310 and the registration mapper.registerModule(new JavaTimeModule()) are no longer needed and can be deleted.

copy() Removed, Use rebuild()

Tests using objectMapper.copy() to create modified mappers fail because copy() is removed. The immutable design requires

jsonMapper.rebuild().enable(SerializationFeature.INDENT_OUTPUT).build()

. The author now injects the auto-configured JsonMapper for normal business code (controllers, services, Kafka) and only uses rebuild() for test-specific or special-protocol variations.

Coexistence with Jackson 2 Dependencies

Third-party SDKs may still require Jackson 2's com.fasterxml.jackson.databind.ObjectMapper. Since Jackson 2 and 3 use different Maven coordinates and packages, they can coexist. Spring Boot 4 provides a transitional module:

org.springframework.boot
    spring-boot-jackson2

This is deprecated and will be removed; the goal is full migration. A useful interim property:

spring:
  jackson:
    use-jackson2-defaults: true

This makes Jackson 3's JsonMapper mimic Spring Boot 3.x + Jackson 2 defaults. The author recommends enabling it during initial migration, passing API tests, then disabling it in a separate task to isolate JSON behavioral changes (null fields, LocalDateTime format, enum output, unknown fields, @JsonProperty, numeric precision, third-party signatures, Kafka/Redis historical message compatibility).

Migration Sequence & Verification

The author's final migration order:

Upgrade Spring Boot to 4.x, let Boot manage dependencies.

Fix Jackson package imports and removed APIs.

Delete manual ObjectMapper beans, rely on auto-configured JsonMapper.

Run regression tests on REST endpoints, Kafka, Redis, and third-party protocols.

If a third-party library lags, allow Jackson 2 and 3 to coexist temporarily rather than blocking the whole upgrade. Spring Boot 4.1.1 manages Jackson 3.1.5, the first LTS branch of 3.x, making now a stable time to migrate. Spring Boot 3.5.16 is the last OSS release of the 3.5 line; official guidance is to move to 4.0.x or 4.1.x.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

migrationBackend DevelopmentJSONspring-bootJacksonobjectmapperSpring Boot 4Jackson 3
LuTiao Programming
Written by

LuTiao Programming

LuTiao Programming is a friendly community offering free programming lessons. We inspire learners to explore new ideas and technologies and quickly acquire job-ready skills.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.