Jackson 3.0.0 (GA) released
(October 3, 2025)
Jackson 3.0.0: when, why, what?
Jackson 3.0.0 was released last week, on October 3rd 2025. It is a big milestone for both the Jackson project and its user community. The “Jackson 3.0 Vision” post I wrote four years ago (!) still offers a good overview of the goals and key ideas behind this second major version bump (the first being 1.x->2.0 back in 2012). In essence, version 3.0 provides a clean foundation for long-term development: it removes accumulated technical debt, streamlines the architecture, and improves ergonomics in ways that were not possible within the constraints of minor releases. Rather than introducing many new features, this release focuses on addressing long-term challenges and enabling sustainable future evolution.
If you’d like to try out Jackson 3.0.0 — and you should! 🙂 — I recommend starting with the post “Taking Jackson 3.0.0-rc1 for a spin”. The instructions there still apply for the 3.0.0 GA release. And if you’re upgrading an existing Jackson 2.x codebase, be sure to check out the Migrating to Jackson 3 document— it covers the key changes and steps needed for a smooth transition.
Introducing Jackson 3 support in Spring” explains the upcoming integration of Jackson 3.0 within the broader Spring ecosystem (huge thanks to the Spring Dev Team, especially Sébastien!) and provides valuable guidance for Spring Boot and Spring Framework users.
And finally, Jackson 3.0 Release Notes includes all documented changes between 2.20 and 3.0 versions.
With that out of the way, let’s take a look at what’s new in Jackson 3.0.
Overview of Jackson 3.0 high-level changes
1. Java Baseline is now 17
Whereas Jackson 2.x only requires Java 8, Jackson 3.0 requires Java 17.
This change simplifies Jackson support of post-Java8 features like Records. 3.0 also provides native support for Java Module system (JPMS), improving interoperability (2.x provides more limited support using Moditect plug-in).
Note that this is just the baseline: Jackson works with newer JDKs, all the way to (at the time of writing this) JDK 25, and can support post-JDK17 language/JDK features as well.
2. Maven group-id, Java package changed to tools.jackson
To allow Jackson 3.x co-exist with 2.x (co-exist meaning that 2.x and 3.x implementations do not collide in classpath), a new Maven group id and Java package names were chosen: tools.jackson (instead of com.fasterxml.jackson of 2.x) — see [JSTEP-1] for full discussion on reasons for doing this.
Necessary changes to work with these changes are detailed in Jackson 3 Migration Guide but the main ones are:
- Change Maven group id in the build files (
pom.xml,build.gradle) by replacingcom.fasterxml.jacksonwithtools.jacksonfor dependencies.
For example,com.fasterxml.jackson.corebecomestools.jackson.core(forjackson-databinddependency). - Change Java
importstatements similarly:
// from Jackson 2.x
import com.fasterxml.jackson.databind.ObjectMapper;
// to Jackson 3.x
import tools.jackson.databind.ObjectMapper;2.1. Maven/Java package renaming exception: jackson-annotations
One exception to this general change is that com.fasterxml.jackson.annotation / jackson-annotations dependency remains unchanged: Jackson 3.0.0 components like jackson-databind depend on jackson-annotations version 2.20. As such neither jackson-annotations Maven dependency nor general Jackson annotation import statements change.
Unfortunately there is one further complication: in-package annotations — like com.fasterxml.databind.annotation.JsonSerialize which is part of jackson-databind and NOT jackson-annotations — do move and their imports need to be changed.
Reason for this exception is to allow core/general Jackson annotations to work with both Jackson 2.x and 3.x without any changes — this is explained in [JSTEP-1].
3. Removal of all Deprecated 2.x functionality (plus renaming)
One major benefit of a new major version is the ability to actually remove obsolete methods, fields and classes marked as @Deprecated in minor releases. With 3.0.0, everything marked as @Deprecated as of Jackson 2.20 has been removed — these were mostly methods with misleading names or obsolete signatures; but also include some obsolete Feature enum values.
In addition to Deprecated-things-removal, many existing core entities (classes) and methods, fields, were renamed — this was done as [JSTEP-6] and [JSTEP-8] efforts. For example:
SerializerProvider(Jackson 2.x) was renamed asSerializationContextin 3.0 (to align with existingDeserializationContext)JsonParser.Features were renamed as eitherJsonReadFeature(JSON-specific) orStreamReadFeature(format-agnostic)
To help users’ upgrade process, Jackson 2.20.0 Javadocs have been augmented in places with descriptions of 3.0 replacements planned. These changes are incomplete: incremental work to update Javadocs continues, please let us know when you find missing cases.
Jackson 3 Migration Guide has sections on “Deprecated method/field/class/functionality removal” and “Core entity, method, field renaming” (although same caveat applies; sections are incomplete)
4. Changes to Default Configuration Settings, behavior
Beyond “cruft removal”, another important area of improvements is configuration settings: specifically the choice of default configuration settings. Many of Jackson 2.x defaults have proven sub-optimal, either based on user feedback (initial choice proven unpopular) or because the default was chosen for backwards-compatibility reasons.
Major version change allowed such default changes, under [JSTEP-2] (which lists all changes).
Examples include:
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES(enabled in 2.x; disabled in 3.0 by default) — changed due to strong user feedback (one of most highly-voted issue ever).MapperFeature.USE_STD_BEAN_NAMING(disabled in 2.x; behavior changed to enabled in 3.0) — originally added as an opt-in feature but really makes sense to always enabled.
5. Immutable ObjectMappers, Configure using Builder
Beyond configuration defaults, another long-term issue with Jackson 2.x configurability is the basic thread-safety (or lack thereof) of configuringObjectMapper instances. Although thread-safe configuration is not complicated — one just has to strictly follow “fully-configure-mapper-before-first-use” pattern — it is possible (and too easy) to use alternate, unsafe approach (configure, use, re-configure, try to use). Unfortunately not only is this possible but it may even work (or seem to work; or sometimes work). Or not. And if not, it is not obvious why.
Jackson 3.x solves this problem by making ObjectMappers fully immutable: the only way to configure mapper instances is by using builder-based construction:
JsonMapper mapper = JsonMapper.builder() // format-specific builders
.addModule(new JodaModule()) // to use Joda date/time types
.enable(JsonWriteFeature.ESCAPE_NON_ASCII) // configure streaming JSON-escaping
.build();One useful addition is the ability to create re-configured instances with rebuild():
JsonMapper mapper2 = mapper.rebuild()
.enable(SerializationFeature.INDENT_OUTPUT)
.build();Builder-style configuration is also used for constructing now-immutable TokenStreamFactory instances (like JsonFactory, YAMLFactory):
YAMLFactory yf = YAMLFactory.builder()
.enable(StreamWriteFeature.STRICT_DUPLICATE_DETECTION)
.build();
YAMLMapper mapper = YAMLMapper.builder(yf)
// configure as necessary
.build();As seen from examples, use of format-specific mappers (JsonMapper, YAMLMapper) is now required for construction: it is no longer possible to use generic ObjectMapper with format-specific TokenStreamFactory instances — no more new ObjectMapper(new YAMLFactory()) calls.
6. Unchecked exceptions (base JacksonException)
Original design for Jackson Exception hierarchy — starting with the base JsonProcessingException — built on the underlying blocking IO (java.io) read/write calls already exposing checked IOException — so Jackson API might as well “piggy-back” on that and make IOException the base of all Jackson exceptions.
This worked quite well until Java 8 and Streams (or functional programming in general) — but with that, use of checked exceptions has become a major inconvenience. So while there is still on-going debate within Java community on “checked vs unchecked exceptions”, it was decided that Jackson 3.0 switches to unchecked RuntimeException as the base. The new ultimate base exception is JacksonException — we took the opportunity to rename exception types too, to reduce use of “JSON” in places where there isn’t actual JSON-dependency.
For full scope of changes — and thinking behind changes — see [JSTEP-4].
7. Embedding of “Java 8 Modules”
Jackson 2.x has 3 add-on modules to support 3 features added by JDK 8:
jackson-module-parameter-names: auto-detection of constructor parameter names (mostly to use with@JsonCreator)jackson-datatype-jdk8: support forjava.util.Optionaland other optional types (OptionalDouble, ...)jackson-datatype-jsr310: support forjava.timeDate/Time types
The reason the functionality was added as modules was because at the time Jackson (2.0 and early 2.x before 2.10 or so) only required Java 5; and to avoid requiring latest JDK 8 (at the time) it made sense to offer support via dynamically added modules.
But with Jackson long since having required Java 8 (and with 3.0 Java 17), it made sense to integrate this functionality: Jackson 3.0 has it all in default ObjectMapper. This means there are 3 fewer modules to register for typical usage.
A related change is the introduction of new DateTimeFeature configuration: it works for all Date/Time types supported (old java.util.Date/Calendar, Joda date/time; Java 8 java.time types):
JsonMapper mapper = JsonMapper.builder()
// 3.0 defaults to writing Dates as ISO-8601; change to timestamps
.enable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
.build();8. Improved Tree Model (JsonNode)
And next-to-last but not least: Tree Model (JsonNode) has been significantly improved. For full changes please refer to [JSTEP-3], but highlights include:
- More configurability with
JsonNodeFeature - Ability to indicate failures with
JsonNodeException(partly due to (6) above, “Unchecked exceptions”) — especially coercion failures - More consistent naming
- More extensive coercion/conversion methods —
intValue(),intValueOpt(),asInt()— across numeric types
9. Deprecated Modules: Hibernate data type, JSON Schema
One more thing… some modules have become semi-abandoned during 2.x development cycle:
- https://github.com/FasterXML/jackson-module-jsonSchema — obsolete by functionality, no owner, no development
- https://github.com/FasterXML/jackson-datatype-hibernate — functionality usable, occasional contributions but no owner/maintainer
and because of this, decision via [JSTEP-9] was to consider them deprecated. No upgrade effort to create (and thereby publish) 3.0.0 versions for either.
This is not a final decision: if maintainer(s) is/are found, Hibernate module(s) in particular may be “revived”. But unless that happens, only 2.x versions are available.
X. Next Up: WHY use Jackson 3.0 over 2.0
Now that we know what 3.0 offers, we can (and should!) consider reasons for using Jackson 3 over established, trusted Jackson 2.
… in the next Blog Post. :)
