Skip to content

feat: migrate to Jackson 3#385

Open
GabrielBBaldez wants to merge 3 commits into
crowdin:masterfrom
GabrielBBaldez:feat/migrate-jackson-3
Open

feat: migrate to Jackson 3#385
GabrielBBaldez wants to merge 3 commits into
crowdin:masterfrom
GabrielBBaldez:feat/migrate-jackson-3

Conversation

@GabrielBBaldez

@GabrielBBaldez GabrielBBaldez commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Purpose

Migrates the SDK from Jackson 2.17.3 to Jackson 3.0.0, as requested in #370.

⚠️ Jackson 3 requires Java 17. This PR therefore bumps the project baseline from Java 8 to Java 17 (build.gradle + CI workflows), which drops Java 8/11 support. That is an inherent consequence of Jackson 3 and a release-level decision — flagging it explicitly.

What changed

  • build.gradle: switched to the tools.jackson BOM (jackson-databind 3.0.0). jackson-annotations intentionally stays under com.fasterxml.jackson (Jackson 3 keeps the annotations package).
  • Java baseline → 17: sourceCompatibility bumped 8 → 17 and the CI workflows (basic.yml, docs.yml) bumped to Java 17 (Jackson 3's minimum). Removed import lombok.var; (3 files) in favor of native var.
  • Imports: com.fasterxml.jackson.{core,databind}.*tools.jackson.* (annotations untouched; JsonFactory moved to tools.jackson.core.json).
  • JacksonJsonTransformer: ObjectMapper is immutable in 3.x, so the mapper is built with JsonMapper.builder() (configure, changeDefaultPropertyInclusion(NON_NULL), defaultDateFormat, addModule, changeDefaultVisibility); derived mappers use rebuild() instead of copy().
  • Custom (de)serializers:
    • JsonSerializer/JsonDeserializerValueSerializer/ValueDeserializer
    • SerializerProviderSerializationContext
    • ContextualDeserializer removed — createContextual is now declared on ValueDeserializer
    • p.getCodec().readTree(p)ctxt.readTree(p); getCurrentToken()currentToken(); node.fieldNames()propertyNames()
    • dropped throws IOException (Jackson exceptions are unchecked in 3.x)
  • Tests: the deserializer unit tests relied on Jackson 2 internals that were removed in 3.x (JsonParser.setCodec, ObjectMapper.getFactory, ObjectMapper.getDeserializationContext). They were rewritten to drive deserialization through a configured mapper (readValue), preserving the same assertions.

Heads-up (behavioral change)

Jackson 3's StdDateFormat serializes UTC dates as ...Z (canonical ISO-8601) instead of ...+00:00. For example 2019-09-23T11:26:54.000+00:002019-09-23T11:26:54.000Z. The affected request fixture was updated. There is no built-in option in Jackson 3's StdDateFormat to restore the +00:00 form; both are valid ISO-8601.

Testing

All 579 tests pass locally (./gradlew test, JDK 17).

This is a breaking change (requires Java 17, new tools.jackson coordinates, and the date-format note above), so it's presumably for the next major release — happy to align on timing/approach.

Closes #370

Migrates the SDK from Jackson 2.17.3 to Jackson 3.0.0. Closes crowdin#370.

- build.gradle: use the tools.jackson BOM (jackson-databind 3.0.0); jackson-annotations stays on com.fasterxml.jackson per Jackson 3
- imports moved from com.fasterxml.jackson.{core,databind} to tools.jackson.* (annotations package unchanged)
- JacksonJsonTransformer: ObjectMapper is immutable in 3.x, rebuilt via JsonMapper.builder() (configure, changeDefaultPropertyInclusion(NON_NULL), defaultDateFormat, addModule, changeDefaultVisibility); derived mappers via rebuild()
- custom (de)serializers ported: JsonSerializer/JsonDeserializer -> ValueSerializer/ValueDeserializer, SerializerProvider -> SerializationContext, ContextualDeserializer removed (createContextual now declared on ValueDeserializer), p.getCodec().readTree(p) -> ctxt.readTree(p), getCurrentToken() -> currentToken(), node.fieldNames() -> propertyNames(), exceptions are unchecked (dropped throws IOException)
- tests: rewrote the deserializer unit tests that relied on removed Jackson 2 internals (JsonParser.setCodec, ObjectMapper.getFactory/getDeserializationContext) to drive deserialization through a configured mapper

BREAKING CHANGE: now requires Jackson 3 (tools.jackson coordinates). Jackson 3's StdDateFormat serializes UTC dates as "...Z" (canonical ISO-8601) instead of "...+00:00"; the affected request fixture was updated accordingly.

All 579 tests pass.
- Jackson 3 requires Java 17, so bump sourceCompatibility to 17 and the CI workflows (basic.yml, docs.yml) to Java 17. This drops Java 8/11 support, which is an inherent consequence of Jackson 3.
- remove 'import lombok.var;' (HttpException, Sandbox, CrowdinApiTest); native var (Java 10+) replaces it.
@GabrielBBaldez

Copy link
Copy Markdown
Contributor Author

Heads-up on the build failure — it turned out to be the key point of this migration: Jackson 3 requires Java 17, but the project currently compiles with Java 8 (basic.yml) and build.gradle had sourceCompatibility = 8. So the build couldn't even read Jackson 3's class files (error: cannot access tools.jackson.databind.annotation.JsonDeserialize).

I pushed the necessary follow-up:

  • bumped sourceCompatibility to 17 and the CI workflows (basic.yml, docs.yml) to Java 17;
  • removed import lombok.var; (in HttpException, Sandbox, CrowdinApiTest) — native var (Java 10+) replaces it.

So migrating to Jackson 3 inherently requires Java 17 and drops Java 8/11 support. That's a release-level decision rather than something this PR can avoid — flagging it explicitly so you can decide whether it fits the intended target release. All 579 tests pass locally on JDK 17.

JaCoCo 0.8.5 cannot read Java 17 class files (major version 61), failing jacocoTestReport. Bump to 0.8.11, which supports Java 17/21.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate to Jackson 3

1 participant