Jackson 2.21.4 → Jackson 3.2.1 · package com.fasterxml.jackson → tools.jackson ·
Camel camel-jackson / camel-jacksonxml → camel-jackson3 / camel-jackson3xml
Jackson 3 is a new major line with a new root package. IM 8.1.0 moves its own code, the
pfx-client API model and the Camel JSON dataformats onto Jackson 3.
The good news first. Most IM customers are not affected: if your routes marshal and unmarshal
JSON through thejacksondataformat and you never wrote Java/Groovy against the Jackson API,
everything keeps working. The changes below matter if you (a) touch Jackson classes from Groovy,
or (b) depend on the exact byte-for-byte shape of produced JSON.
1. What changed at a glance
|
|
IM 8.0.x |
IM 8.1.0 |
|---|---|---|
|
Root package |
|
|
|
Annotations package |
|
unchanged — still |
|
Camel dataformat component |
|
|
|
Dataformat name in route XML |
|
unchanged |
|
Exceptions |
checked |
unchecked |
|
|
mutable ( |
immutable — configure via builder |
|
Property order in output |
declaration order |
alphabetical by default |
|
|
needed |
built in |
The annotations package did NOT move
This surprises people, so it is worth stating plainly: Jackson 3 has no tools.jackson.annotation
package. tools.jackson.core:jackson-databind itself depends on
com.fasterxml.jackson.core:jackson-annotations. Your DTO annotations stay exactly as they are:
import com.fasterxml.jackson.annotation.JsonProperty // still correct in IM 8.1.0
import com.fasterxml.jackson.annotation.JsonIgnore // still correct
2. Changes that affect customer scripts
2.1 Sandbox whitelist moved to tools.jackson — DEPLOY-FAIL
The Groovy sandbox allows a fixed list of classes. The Jackson entries changed package, so a script
importing the old ones is rejected.
// BEFORE (IM 8.0.x)
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.JsonToken
// AFTER (IM 8.1.0)
import tools.jackson.databind.JsonNode
import tools.jackson.core.JsonParser
import tools.jackson.core.JsonToken
This fails rather than misbehaves — the class simply is not on the allow-list any more.
2.2 ObjectMapper is immutable — DEPLOY-FAIL / RUNTIME
In Jackson 3 an ObjectMapper cannot be reconfigured after construction. The mutator methods are
gone; configuration happens on a builder.
// BEFORE
def mapper = new ObjectMapper()
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
mapper.registerModule(new JavaTimeModule())
mapper.setDateFormat(new StdDateFormat())
// AFTER
import tools.jackson.databind.json.JsonMapper
def mapper = JsonMapper.builder()
.disable(tools.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.defaultDateFormat(new StdDateFormat())
.build()
// no JavaTimeModule needed - java.time is supported out of the box
To adjust an existing mapper, rebuild it:
def tuned = mapper.rebuild().enable(SomeFeature.X).build()
2.3 Parsing errors are unchecked now — SILENT (error handling)
JsonProcessingException and the IOException signatures are replaced by unchecked
tools.jackson.core.JacksonException (malformed input surfaces as
tools.jackson.core.exc.StreamReadException).
// BEFORE
try {
mapper.readValue(body, Map)
} catch (IOException e) { // AFTER: never thrown -> catch block is dead code
handleBadPayload(e)
}
// AFTER
try {
mapper.readValue(body, Map)
} catch (tools.jackson.core.JacksonException e) {
handleBadPayload(e)
}
This is the dangerous one. A catch (IOException) block does not fail to compile in Groovy — it
simply never matches, so a payload that used to be handled gracefully now propagates as an unhandled
error. Search your scripts for catch blocks around JSON parsing.
2.4 TextNode renamed to StringNode — DEPLOY-FAIL
// BEFORE
TextNode.valueOf("x")
// AFTER
StringNode.valueOf("x")
Other node types (ObjectNode, ArrayNode, IntNode, BooleanNode, NullNode, DecimalNode, …)
keep their names.
3. Changes that affect produced JSON
3.1 Property order — handled by IM for the Pricefx API, relevant for your own mappers
Jackson 3 enables SORT_PROPERTIES_ALPHABETICALLY by default; Jackson 2 did not. The same object
therefore serialises with its fields in a different order.
// Jackson 2 (declaration order)
{"operator":"equals","fieldName":"label","value":"Test"}
// Jackson 3 default (alphabetical)
{"fieldName":"label","operator":"equals","value":"Test"}
What IM does for you. For calls to the Pricefx API, IM explicitly disables alphabetical
sorting so the wire format is unchanged from IM 8.0.x. You do not need to do anything for
pfx-api: / pfx-client traffic.
Where it can still reach you. If one of your routes marshals JSON with the jackson dataformat
and the receiving system is order-sensitive, or if you assert on exact JSON strings in your own
tests, expect alphabetical order from the dataformat. Well-behaved JSON consumers do not care about
member order — but strict schema validators and string comparisons do.
3.2 Trailing content is rejected by default — RUNTIME
Jackson 3 enables FAIL_ON_TRAILING_TOKENS by default. Input with anything after the first JSON
value (including a stray second document, or a malformed payload that happens to have parsed so far)
now throws where Jackson 2 quietly ignored the remainder.
What IM does for you. IM deliberately disables this for the two paths that read
customer-supplied and external-system data — filter definitions and REST/HTTP responses handled by
pfx-client — to preserve IM 8.0.x leniency. Your own ObjectMapper instances get the Jackson 3
default unless you disable it yourself.
3.3 Unknown properties are ignored by default
Jackson 3 turns FAIL_ON_UNKNOWN_PROPERTIES off by default (Jackson 2 had it on). Deserialising
a payload with extra fields now succeeds where it previously threw.
Watch for. Scripts that relied on the exception as validation — "if it parses, the payload is the
right shape" is no longer true by default. Enable it explicitly if you depend on it:
JsonMapper.builder().enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES).build()
3.4 java.time is built in
JavaTimeModule no longer exists and is not needed; LocalDate, Instant and friends serialise out
of the box. Remove the registration — it will not compile otherwise.
3.5 Large payloads
IM applies its integration.jackson.max-string-length limit to both Jackson majors, so the
protection you configured on IM 8.0.x still applies. Jackson 3 also carries its own
StreamReadConstraints defaults; note that Jackson 3 lowered the default maximum nesting depth
from 1000 to 500 — deeply nested JSON that previously parsed could now be rejected.
4. Camel dataformat
The component behind the jackson dataformat changed from camel-jackson to camel-jackson3.
<!-- unchanged in your route XML -->
<unmarshal><json library="Jackson"/></unmarshal>
<marshal><json library="Jackson"/></marshal>
The dataformat name and syntax are unchanged — Camel resolves whichever implementation is on the
classpath. What changes is the behaviour underneath it: the defaults in §3 apply.
pfx-event with jsonParser=jackson likewise keeps its configuration and moves to Jackson 3.
5. Where Jackson 2 still exists
Jackson 2 has not disappeared from the runtime; it is pulled in by four third-party dependencies
that have no Jackson 3 build yet:
|
dependency |
Jackson 2 artifacts it needs |
used for |
|---|---|---|
|
|
|
Rest DSL |
|
|
|
metrics serialisation |
|
|
|
GCS client internals |
|
|
|
k8s model |
No IM code imports com.fasterxml.jackson.databind or .core. These are internal to the libraries
above and will disappear as each ships a Jackson 3 build.
6. Search patterns for your repository
|
What to find |
Pattern |
Section |
|---|---|---|
|
Old Jackson imports |
|
§2.1 |
|
Annotation imports (leave alone) |
|
§1 |
|
Mapper mutation |
|
§2.2 |
|
Dead catch blocks |
|
§2.3 |
|
|
|
§2.4 |
|
|
|
§3.4 |
|
Exact-JSON assertions |
|
§3.1 |
7. Sources
-
Apache Camel
camel-jackson3component documentation -
Verified against IM's own migration: IM's 4 000+ tests and
pfx-client's 513 tests run on
Jackson 3.2.1; the behaviours in §3.1, §3.2 and §3.3 were each observed and handled during that
migration.