feat: migrate from Jackson 2 to Jackson 3 (tools.jackson) for Spring Boot 4 native support#2306
Closed
StringKe wants to merge 1 commit into
Closed
feat: migrate from Jackson 2 to Jackson 3 (tools.jackson) for Spring Boot 4 native support#2306StringKe wants to merge 1 commit into
StringKe wants to merge 1 commit into
Conversation
Migrates the entire DGS Framework from Jackson 2 (com.fasterxml.jackson.*) to Jackson 3 (tools.jackson.*) so that DGS aligns natively with Spring Boot 4 and Spring Framework 7 (where the default ObjectMapper is replaced by tools.jackson.databind.json.JsonMapper). Refs Netflix#2284, Netflix#2296 What changed: - BaseDgsQueryExecutor.objectMapper is now a JsonMapper built via the Jackson 3 builder pattern. Public field type changes from ObjectMapper to JsonMapper. - JsonPath integration switches to json-path 3.0.0's Jackson3JsonProvider and Jackson3MappingProvider (the platform BOM bumps json-path from 2.9.0 to 3.0.0; Spring Boot's pin is overridden via the json-path.version property). - graphql-dgs-client public APIs now accept JsonMapper instead of ObjectMapper across GraphQLClient, MonoGraphQLClient, WebClientGraphQLClient, RestClientGraphQLClient, GraphQLResponse, and the SSE/WebSocket variants. - GraphQLRequestOptions custom serializer/deserializer extends Jackson 3's ValueSerializer<T>/ValueDeserializer<T> (renamed from JsonSerializer/ JsonDeserializer). The serialize override receives SerializationContext (renamed from SerializerProvider). - MultipartFileSerializer extends Jackson 3 StdSerializer; writeStringField is renamed to writeStringProperty per the Jackson 3 streaming API. - Drop dependencies on jackson-datatype-jdk8, jackson-module-parameter-names, and jackson-datatype-jsr310. JDK 8 / parameter-names / java.time support is built into jackson-databind 3.x and discovered automatically. - READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE moved from DeserializationFeature to tools.jackson.databind.cfg.EnumFeature in J3. - WRITE_DATES_AS_TIMESTAMPS moved from SerializationFeature to tools.jackson.databind.cfg.DateTimeFeature in J3. - FAIL_ON_NULL_FOR_PRIMITIVES is now disabled explicitly on BaseDgsQueryExecutor.objectMapper because Jackson 3 flipped its default to true; DGS GraphQL responses regularly omit non-selected primitives and would otherwise break extractValueAsObject. - JPMS module-info requires clauses updated from com.fasterxml.jackson.* to tools.jackson.* (databind/core/datatype/module). The annotation module remains com.fasterxml.jackson.annotation because Jackson 3 intentionally reuses the Jackson 2 jackson-annotations 2.21 jar — the annotation classes (JsonProperty, JsonCreator, JsonIgnoreProperties, JsonSubTypes, JsonTypeInfo, etc.) are unchanged in Jackson 3. - OperationMessageTest's malformed-JSON assertion broadens from DatabindException to JacksonException; in Jackson 3 parser-level failures throw StreamReadException, a sibling of DatabindException under JacksonException. - All dependency-lock files regenerated with the new resolutions. BREAKING CHANGES - Public APIs that previously accepted com.fasterxml.jackson.databind.ObjectMapper (BaseDgsQueryExecutor.objectMapper, GraphQLClient.createCustom, WebClientGraphQLClient, RestClientGraphQLClient, GraphQLResponse, MonoGraphQLClient and the custom variants) now require tools.jackson.databind.json.JsonMapper. There is no compatibility shim; callers must migrate. - Custom client-side ValueSerializer/ValueDeserializer implementations must extend the new Jackson 3 base classes; serialize() takes SerializationContext, deserialize() takes DeserializationContext. - json-path is forced to 3.0.0 (overrides Spring Boot 4's 2.9.0 pin); consumers using json-path APIs transitively through DGS may need to adjust to json-path 3.x.
Collaborator
|
Closing since we've released Jackson3 support in v12.0.0. It's most similar to your first alternative considered
But the way we've implemented it does not force Jackson2 on the classpaths of those who want to fully embrace Jackson3. Please feel free to open an issue if you're having trouble with the released solution. |
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.
Pull request checklist
Pull Request type
Changes in this PR
Migrates the entire DGS Framework from Jackson 2 (
com.fasterxml.jackson.*) to Jackson 3 (tools.jackson.*) so that DGS aligns natively with Spring Boot 4 / Spring Framework 7, wheretools.jackson.databind.json.JsonMapperreplacescom.fasterxml.jackson.databind.ObjectMapperas the default mapper.Issue #2284, also addresses the underlying Jackson 3 conflict reported in #2296.
What changed
BaseDgsQueryExecutor.objectMapperis now aJsonMapperbuilt via the Jackson 3 builder pattern. Public field type changes fromObjectMappertoJsonMapper.Jackson3JsonProviderandJackson3MappingProvider. The platform BOM bumps json-path from 2.9.0 to 3.0.0; Spring Boot 4's pin is overridden via thejson-path.versionproperty.graphql-dgs-clientpublic APIs acceptJsonMapperinstead ofObjectMapperacrossGraphQLClient,MonoGraphQLClient,WebClientGraphQLClient,RestClientGraphQLClient,GraphQLResponse, and the SSE/WebSocket variants.GraphQLRequestOptionscustom serializer/deserializer extends Jackson 3'sValueSerializer<T>/ValueDeserializer<T>(renamed fromJsonSerializer/JsonDeserializer). Theserializeoverride receivesSerializationContext(renamed fromSerializerProvider).MultipartFileSerializerextends Jackson 3StdSerializer;writeStringFieldis renamed towriteStringPropertyper the J3 streaming API.jackson-datatype-jdk8,jackson-module-parameter-names, andjackson-datatype-jsr310dependencies. JDK 8 / parameter-names /java.timesupport is built intotools.jackson.databind3.x and discovered automatically.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUEmoved fromDeserializationFeaturetotools.jackson.databind.cfg.EnumFeaturein J3.WRITE_DATES_AS_TIMESTAMPSmoved fromSerializationFeaturetotools.jackson.databind.cfg.DateTimeFeaturein J3.FAIL_ON_NULL_FOR_PRIMITIVESis explicitly disabled onBaseDgsQueryExecutor.objectMapperbecause Jackson 3 flipped its default totrue. DGS GraphQL responses regularly omit non-selected primitive fields and would otherwise breakextractValueAsObject.module-inforequiresclauses updated fromcom.fasterxml.jackson.*totools.jackson.*(databind/core/datatype/module). The annotation module remainscom.fasterxml.jackson.annotationbecause Jackson 3 deliberately reuses the existing Jackson 2jackson-annotationsartifact (resolved to 2.20 in this build via Spring Boot 4'sjackson-2-bom) — annotation classes (JsonProperty,JsonCreator,JsonIgnoreProperties,JsonSubTypes,JsonTypeInfo, etc.) are unchanged in Jackson 3.OperationMessageTest's malformed-JSON assertion broadens fromDatabindExceptiontoJacksonException; in Jackson 3 parser-level failures throwStreamReadException, a sibling ofDatabindExceptionunderJacksonException.dependencies.lockfiles regenerated with the new resolutions.Breaking changes
com.fasterxml.jackson.databind.ObjectMapper(BaseDgsQueryExecutor.objectMapper,GraphQLClient.createCustom,WebClientGraphQLClient,RestClientGraphQLClient,GraphQLResponse,MonoGraphQLClientand the custom variants) now requiretools.jackson.databind.json.JsonMapper. There is no compatibility shim; callers must migrate.ValueSerializer/ValueDeserializerimplementations must extend the new Jackson 3 base classes;serialize()takesSerializationContext,deserialize()takesDeserializationContext.Verification
./gradlew checkis green (compile, ktlint, all tests across every module).grep -rn "com.fasterxml.jackson" --include='*.kt' --include='*.kts' --include='*.java' .returns onlyjackson-annotationsreferences, which is intentional — Jackson 3 deliberately reuses the Jackson 2 annotations artifact.Issue #2284
Alternatives considered
spring-boot-jackson2compatibility shim: keeps Jackson 2 alongside Jackson 3 via the Spring Boot 4 bridge module. Rejected because the goal is for DGS to natively align with the Spring Boot 4 default (Jackson 3) without forcing every consumer to drag in the deprecated Jackson 2 module.org.springframework.boot.jackson2.autoconfigure.Jackson2AutoConfigurationis annotated@Deprecated(since = "4.0.0", forRemoval = true)and the Spring Boot Javadoc states it will be removed in Spring Boot 4.3.0 in favor of Jackson 3.ObjectMapper-typed public APIs as deprecated: would soften the break but contradicts the request in feature: Support Jackson 3 in DGS #2284 for native Jackson 3 support. The annotation classes are reused as-is precisely because they did not need to change; the rest of the API rename was unavoidable per the Jackson 3 design.