Get ahead
VMware offers training and certification to turbo-charge your progress.
Learn moreThis is a new blog post in the Road to GA series, this time sharing more details on the new Jackson 3 support, just a few days after Jackson 3.0.0 GA release, about to be introduced in Spring Boot 4 and related Spring portfolio projects.
Jackson is by far the most used JSON library on the JVM, and the introduction of the Jackson 3 support in Spring is the opportunity for us to provide additional enhancements, as a follow-up of the popular Jackson integration improvements in Spring that I announced more than 10 years ago!
When the Spring team works on leveraging new versions of popular open source libraries, while it may not be obvious, a significant part of the work is sometimes collaborating with the maintainers on refinements that will benefit the wider community.
Jackson 3 is a great illustration of that and I would like to thank Tatu Saloranta (the Jackson project lead) for his willingness to take our feedback into account during the release candidate phase - which has allowed the following refinements:
JsonWriteFeature.ESCAPE_FORWARD_SLASHES
default value@JsonCreator
The general principle is that, as of Spring Boot 4 and Spring Framework 7, the Spring portfolio is:
Main exception to this is Spring AI which intends to introduce Jackson 3 support in its 2.0 release in the first half of 2026.
More specifically, Spring Boot 4 is:
spring-boot-starter-json
and spring-boot-starter-jackson
starter dependenciesApplications migrating to Spring Boot 4 are encouraged to migrate to Jackson 3, even if it’s still possible to use Jackson 2 with Spring Boot 4 (see related section below). Transitive dependencies still depending on Jackson 2 remain supported and will benefit from the Jackson 2 dependency management.
This section focuses on the most important migration steps for typical Spring Boot applications, see the Jackson 3 migration guide for more details on other aspects. Related Open Rewrite recipes can help to automate some of those changes, and Spring Application Advisor will provide the most comprehensive option for migrating your Spring Boot application incrementally.
The first breaking change you will encounter when upgrading is probably the Jackson package (and dependency groupID) change from com.fasterxml.jackson
to tools.jackson
except for jackson-annotations which remains unchanged for backward-compatibility reasons.
Jackson 3 has changed some default settings compared to Jackson 2, so you should either adapt your tests accordingly (recommended when you can), or customize Jackson 3 configuration to restore some of the previous defaults.
The changes most likely to break you tests are the following:
MapperFeature.SORT_PROPERTIES_ALPHABETICALLY
now set to true.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS
now known as DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS
has been changed to false to serialize dates as ISO-8601 strings.If you prefer at least initially keep using default settings as close as possible as Jackson 2, you can use:
@Bean
JsonMapperBuilderCustomizer jacksonCustomizer() {
return builder -> builder.configureForJackson2();
}
Some former Jackson 2 modules are now built in Jackson 3, like the parameter-names or datatype-jsr310 ones. Other modules previously enabled via the Jackson2ObjectMapperBuilder
are now discovered automatically via the JDK service loader facility for the converters and codecs provided with Spring Framework.
It is also of course possible to configure custom ones via JsonMapper.Builder
.
Jackson 3 introduces a lot of changes and enhancements, but from a Spring perspective one of the most important ones to understand and embrace is the switch from a mutable ObjectMapper
in Jackson 2 to an immutable JsonMapper
in Jackson 3.
JsonMapper
, which extends ObjectMapper
, is specific to the JSON format, following a similar pattern than other formats (XmlMapper
, YAMLMapper
, SmileMapper
, etc.) and Spring support has been updated to use this format specific variant, following Jackson 3 best practices.
Also with Jackson and Spring defaults mostly aligned, and the introduction of a first class JsonMapper.Builder
, Spring Framework does not provide an equivalent for Jackson2ObjectMapperBuilder
, you should just use the Jackson builder.
For example, with Spring Boot 3 and its Jackson 2 support, the programmatic equivalent of spring.jackson.serialization.indent-output=true
was:
@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() {
return builder -> builder.indentOutput(true);
}
With Spring Boot 4 and its Jackson 3 support, it is:
@Bean
JsonMapperBuilderCustomizer jacksonCustomizer() {
return builder -> builder.enable(SerializationFeature.INDENT_OUTPUT);
}
The now deprecated MappingJackson2HttpMessageConverter
was extending GenericHttpMessageConverter
which does not allow to pass properly additional serialization information like the serialization view or FilterProvider
, hence the need for a MappingJacksonValue
wrapper.
For example, let say we are annotating a User
record with @JsonView(Summary.class)
to identify a subset of its components to serialize or deserialize:
public record User(
@JsonView(Summary.class) String firstname,
@JsonView(Summary.class) String lastname,
LocalDate birthdate,
@JsonView(Summary.class) String email,
String address,
int postalCode,
String city,
String country) {
}
With Spring Framework 6 and before, on client side you had to use a MappingJacksonValue
wrapper to specify the Summary
JSON view should be used.
var user = new User("Marcel", "Martin", LocalDate.of(1971, 7, 12),
"[email protected]", "1234 rue Gambetta", 69002, "Lyon", "France");
var jacksonValue = new MappingJacksonValue(user);
jacksonValue.setSerializationView(Summary.class);
var response = this.restTemplate.postForObject("http://localhost:8080/create", jacksonValue, String.class);
This allows to serialize only the record components annotated with @JsonView(Summary.class)
:
{
"firstname" : "Marcel",
"lastname" : "Martin",
"email" : "[email protected]"
}
As of Spring Framework 7, you can leverage the fact that the new JacksonJsonHttpMessageConverter
based on Jackson 3 is implementing SmartHttpMessageConverter
which supports serialization hints, so you can write instead:
var user = new User("Marcel", "Martin", LocalDate.of(1971, 7, 12),
"[email protected]", "1234 rue Gambetta", 69002, "Lyon", "France");
var response = this.restClient.post().uri("http://localhost:8080/create")
.hint(JsonView.class.getName(), Summary.class).body(user)
.retrieve().body(String.class);
No more mutable wrapper, just optional hints.
Applications migrating to Spring Boot 4 are encouraged to migrate to Jackson 3 but can continue to use Jackson 2 or even use Jackson 2 and 3 at the same time if needed. Just be aware it may require adding Jackson 2 dependencies and some manual configuration.
With Spring Boot 4 and Spring MVC, if you exclude Jackson 3 dependencies and add Jackson 2 ones, the Jackson 2 support will be used by default as it will be detected by WebMvcConfigurationSupport
.
If you have both Jackson 2 and Jackson 3 in the classpath, Spring Framework introduces a new org.springframework.http.converter.HttpMessageConverters
type and a related Spring Boot 4 customizer which allows to force using Jackson 2 pretty easily:
@Bean
@SuppressWarnings("removal")
public ServerHttpMessageConvertersCustomizer jackson2ServerConvertersCustomizer() {
return builder -> builder.jsonMessageConverter(new MappingJackson2HttpMessageConverter());
}
The related pull-request is not yet merged and still subject to refinements, but it is worth to notice that in addition to introducing Jackson 3 support and deprecating Jackson 2 one, Spring Security 7.0 is going to make its Jackson 3 support safer by disabling default global typing (see this blog post for more background).
Instead, it leverages a PolymorphicTypeValidator where only Spring Security types are allowed by default, and provide the capability for applications to add their own types, for example:
ClassLoader loader = getClass().getClassLoader();
BasicPolymorphicTypeValidator.Builder typeValidatorBuilder = BasicPolymorphicTypeValidator.builder()
.allowIfSubType(CustomGrantedAuthority.class);
JsonMapper mapper = JsonMapper.builder()
.addModules(SecurityJacksonModules.getModules(loader, typeValidatorBuilder))
.build();
Due to the Jackson 3 changes and the disabling of global default typing, Jackson 2 and Jackson 3 serialized data format will be different, but in in order to ease the migration of applications storing Jackson 2 in databases for example, a Jackson 2 compatibility mode is going to be provided in order to allow migrating to Spring Boot 4 and Spring Security 7, while still using the very same Jackson 2 data format with Jackson 3.
Spring Data 4.0 ships with full support for Jackson 3 for its core modules. Applications migrating to Spring Data 4 are encouraged to migrate to Jackson 3 but can continue to use Jackson 2 or even use Jackson 2 and 3 at the same time if needed. Just be aware that Jackson 3 ships with a different set of defaults that may require either a migration of your persistent data or updating Jackson 3 defaults to match Jackson 2 settings.
As Spring Data forms a larger set of projects, let's explore each module separately:
Spring Data Commons adding support for Jackson 3 with a fallback to Jackson 2 if only Jackson 2 is on the classpath. This applies mostly to Web support through ProjectingJacksonHttpMessageConverter
and SpringDataWebConfiguration
.
JacksonResourceReader
and JacksonRepositoryPopulatorFactoryBean
are Jackson 3-based variants of Jackson2ResourceReader
respective Jackson2RepositoryPopulatorFactoryBean
.
If you’re using Jackson 2 together with Spring Data’s XML namespace support (<repository:jackson2-populator …>
) and you want to migrate to Jackson 3, then you will have to define a JacksonRepositoryPopulatorFactoryBean
bean in your Java configuration.
If you happen to use SpringDataJacksonModules
, then you want to consider migrating towards SpringDataJackson3Modules
for a Jackson 3-based arrangement of your modules.
Spring Data Redis 4.0 ships with JacksonHashMapper
, JacksonJsonRedisSerializer
, and GenericJacksonJsonRedisSerializer
implementations for Jackson 3. When using JacksonObjectReader
and JacksonObjectWriter, make sure to retrofit your implementations using Jackson2ObjectReader
respective Jackson2ObjectWriter
as class naming has been aligned for a consistent scheme.
Spring Data REST is essentially a large wrapper around Jackson that doesn't support an operating mode using Jackson 2. If you want to use the new Spring Data REST version then your application must migrate to Jackson 3. Similar goes for Spring HATEOAS as both frameworks make heavy usage of Jackson.
The larger ecosystem is slowly catching up with Jackson 3. Couchbase, Elasticsearch, and some drivers use Jackson 2 internally and will continue doing so. In most cases, Jackson usage within these components doesn't relate to your entities as it is their mechanism for a JSON parser and writer.
Jackson 3 brings strong benefits in terms of security, API, default configuration and capabilities, but it also comes with breaking changes that will require some migration work, the Spring team fully realizes that and has put significant efforts in providing the best possible arrangement and related guidance as well as offering industry leading extended support on the previous version to give you the time to upgrade.
As usual, we are looking for feedback and will do our best to refine our guidance, documentation and answer to your related questions.