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.
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.jackson → tools.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_nullFor 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-jackson2This is deprecated and will be removed; the goal is full migration. A useful interim property:
spring:
jackson:
use-jackson2-defaults: trueThis 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
