The first time I ran a Jackson 3.1.2 build against a codebase that had been on Jackson 2 since 2019, the compile output had three categories of error: removed methods I expected, removed methods I had completely forgotten about, and one that genuinely surprised me — a custom deserialiser that silently stopped working because it depended on mutable ObjectMapper reconfiguration after injection.
Jackson 3 is not an incremental release. It raises the Java baseline to 17, renames the entire package namespace, makes mapper configuration immutable, inlines three modules that previously required separate dependencies, and removes the APIs most responsible for serialisation CVEs. The changes below are the ones that actually matter when you’re deciding whether to upgrade — not a spec recap, but the differences that will touch your code.
The Change That Will Actually Break Your Code First
Before the full comparison table: in every Jackson 3 upgrade I have seen, the first breaking change that isn’t a compile error is the mapper immutability model. If anywhere in your codebase you have code that retrieves an ObjectMapper bean and calls a configure method on it after instantiation — even once, in a test setup — that code is silently a no-op in Jackson 3. The mapper built by JsonMapper.builder().build() is locked. The call succeeds, nothing throws, but your configuration change has no effect. Tests pass. Production behaves differently. Audit every location where ObjectMapper is touched after construction before bumping the version.
At a Glance: Jackson 2 vs Jackson 3
| Feature | Jackson 2.x (2.17.2) | Jackson 3.x (3.1.2) |
|---|---|---|
| Java baseline | Java 8+ | Java 17+ (all core modules) |
| Package namespace | com.fasterxml.jackson.* | tools.jackson.* (annotations stay at com.fasterxml.jackson.annotation) |
| Maven Group ID | com.fasterxml.jackson.core | tools.jackson.core (annotations: com.fasterxml.jackson.core) |
| Primary mapper class | ObjectMapper | JsonMapper (builder); ObjectMapper still present |
| Mapper construction | Mutable: new ObjectMapper() + chained setters | Immutable: JsonMapper.builder().build() |
| Exception hierarchy | JsonProcessingException extends IOException (checked) | JacksonException extends RuntimeException (unchecked) |
| Java records | Supported from 2.12 via jackson-module-parameter-names | Native, zero extra dependency |
| Optional<T> | Requires jackson-datatype-jdk8 | Built into core |
| java.time.* types | Requires explicit JavaTimeModule registration | Auto-registered |
| enableDefaultTyping() | Deprecated in 2.10, removed in 2.16 | Does not exist — compile error |
| Security posture | Gadget attacks possible with misconfiguration | Tighter by default; removed dangerous APIs |