Upgrade jackson from 2.22.0 to 3.2.0#628
Draft
sabieber wants to merge 4 commits into
Draft
Conversation
…pgrade Assisted-by: Claude Fable 5 Fixes: SIRI-1149
Switches jackson-databind to the new tools.jackson.core coordinates and adjusts all imports accordingly. The jackson-annotations artifact intentionally stays on the com.fasterxml.jackson 2.x line, as Jackson 3 continues to use it. The jackson-datatype-jsr310 dependency is removed because java.time support is built into jackson-databind 3. Json.MAPPER is now constructed via the builder API (mappers are immutable in Jackson 3) based on builderWithJackson2Defaults(), so the wire format and parsing behavior remain unchanged for API consumers despite Jackson 3 flipping several serialization defaults (alphabetical property ordering, dates, enums, stricter parsing). Adopting the new defaults remains a deliberate, separate step. Jackson 3 no longer honors @jsonvalue on subclasses of Number, which silently broke Amount serialization to a locale-dependent string. As class-level @JsonSerialize annotations are consulted before the standard Number handling, Amount now declares an explicit serializer replicating the previous behavior. Unlike a mapper-registered module, this also covers mappers constructed outside of Json and node serialization via toString(). Note that node.toString() no longer serializes POJO nodes through the mapper - Json.write() must be used instead. Jackson exceptions are now unchecked; the try-prefixed methods in Json keep their signatures with JacksonException in place of JsonProcessingException. Assisted-by: Claude Fable 5 Fixes: SIRI-1149
sabieber
marked this pull request as draft
July 10, 2026 12:31
mkeckmkeck
approved these changes
Jul 13, 2026
fhaScireum
approved these changes
Jul 13, 2026
idlira
approved these changes
Jul 13, 2026
This was referenced Jul 13, 2026
Jackson 2 serialized Amount via its @jsonvalue accessor, whose JsonValueSerializer treated a null accessor result as empty, so that @JsonInclude(NON_EMPTY) suppressed properties holding empty amounts. The explicit serializer introduced in the Jackson 3 migration only replicated the value output, causing such properties to be written as null instead of being omitted. Overrides isEmpty() in Amount.JacksonSerializer to treat NOTHING as empty, restoring the Jackson 2 behavior. This surfaced in sellsite, where a model class annotated with @JsonInclude(NON_EMPTY) suddenly emitted "maxValue": null entries that Jackson 2 omitted. Assisted-by: Claude Fable 5 Fixes: SIRI-1149
This seems a bit quirky so it seems like a good idea to document his and also as a guard against undocumented behaviour changes (which the maintainers are known for). Assisted-by: Claude Fable 5 Fixes: SIRI-1149
mkeckmkeck
approved these changes
Jul 15, 2026
jakobvogel
approved these changes
Jul 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
BREAKING CHANGES
Upgrades Jackson from 2.22.0 to 3.2.0 across the sirius stack. Jackson 3 uses new Maven coordinates and Java packages — see the official Jackson 3 migration guide and release notes for the complete list of renames and behavioral changes.
What applications using the sirius framework have to change:
com.fasterxml.jackson.*→tools.jackson.*(annotations stay oncom.fasterxml.jackson.annotation); dropjackson-datatype-jsr310andJavaTimeModuleregistrations (built-in now).JsonProcessingException→JacksonException, deadcatch (IOException)blocks), method renames (asText()→asString()etc.,writeFieldName()→writeName()etc.), builder-based mapper/generator configuration — see the migration guide for details.Description
Migrates sirius-kernel from Jackson 2.22.0 to Jackson 3.2.0 (managed via the Jackson 3 BOM in sirius-parent, see related PR).
Dependency changes
jackson-databindmoves to the newtools.jackson.corecoordinates (Jackson 3 uses new Maven coordinates and Java packages, so both major versions can coexist on the classpath for third-party dependencies still using Jackson 2).jackson-annotationsintentionally stays on thecom.fasterxml.jackson2.x line — Jackson 3 continues to use it, so all@Json...annotations keep working unchanged.jackson-datatype-jsr310is removed, asjava.timesupport is built into jackson-databind 3.Json
ObjectMappers are immutable in Jackson 3, soJson.MAPPERis now constructed via the builder API. It is based onJsonMapper.builderWithJackson2Defaults(), which keeps the wire format and parsing behavior stable for API consumers, since Jackson 3 flips several defaults (alphabetical property ordering, date/enum handling, stricter parsing). Adopting the new defaults is left as a deliberate, separate step.try...methods keep their signatures withJacksonExceptionreplacingJsonProcessingException.Amount
@JsonValueon subclasses ofNumber— the standard number serializer takes precedence and would emit the locale-dependenttoString()representation (see upstream regression, to be reported against jackson-databind). Since class-level@JsonSerializeannotations are consulted before the standard handling,Amountnow declares an explicit nested serializer replicating the previous behavior. Unlike registering a serializer onJson.MAPPER, this also covers mappers constructed elsewhere and node serialization viatoString().NOTHING→null, rounding of non-rounded amounts, full precision for rounded amounts).Notes for consumers
asText()→asString(),textValue()→stringValue(),isTextual()→isString().null/0/false/""for missing, null-valued or type-mismatched properties — Jackson 3 mostly throwsJsonNodeExceptioninstead. Both behaviors are pinned by executable documentation tests inJsonTest(Jackson 3 version in this branch; Jackson 2 counterpart onfeature/sbi/SIRI-1149-before). The test-verified differences:textValue()→stringValue()nullstringValue(null)nullstringValue(null)nullnullnull(unchanged)asText()→asString()null"null"""asString("")¹""asString("")longValue()"42"0longValue(0L)²0longValue(0L)null/ missing0longValue(0L)asLong()"foo"0asLong(0L)booleanValue()falsebooleanValue(false)null/ missingfalsebooleanValue(false)asBoolean()"foo"falseasBoolean(false)¹ deliberately yields
""instead of Jackson 2's literal"null"— code actually depending on the string"null"needs a manualisNull()check.²
asLong(0L)is not equivalent here: it would convert"42"to42where Jackson 2'slongValue()returned0.Unchanged: matching-type reads, the
asXxx()scalar coercions (asString()on numbers,asLong()on"42",asBoolean()on"true"/numbers) and theasXxx()defaults for null/missing. Where absence should be handled explicitly rather than defaulted, prefer theOptionalvariants (stringValueOpt(),longValueOpt(), ...).Additional Notes
Checklist