Skip to content

Fix NullPointerException resolving type hints for JSON with duplicate properties#3397

Open
ctomc wants to merge 1 commit into
spring-projects:mainfrom
ctomc:issue/gh-3396-typeresolver-npe
Open

Fix NullPointerException resolving type hints for JSON with duplicate properties#3397
ctomc wants to merge 1 commit into
spring-projects:mainfrom
ctomc:issue/gh-3396-typeresolver-npe

Conversation

@ctomc

@ctomc ctomc commented Jul 10, 2026

Copy link
Copy Markdown

Problem

GenericJacksonJsonRedisSerializer (Jackson 3, default typing enabled) throws a NullPointerException when deserializing any value whose JSON contains a duplicate property name.

TypeResolver.readTree(byte[]) builds the JSON node tree with a DeserializationContext obtained from ObjectMapper._deserializationContext(), which is never bound to the parser. Its stream-read capabilities therefore stay null, and the first time BaseNodeDeserializer._handleDuplicateProperty consults StreamReadCapability.DUPLICATE_PROPERTIES it fails:

java.lang.NullPointerException: Cannot invoke
"tools.jackson.core.util.JacksonFeatureSet.isEnabled(...)" because "this._readCapabilities" is null
    at tools.jackson.databind.DeserializationContext.isEnabled(DeserializationContext.java:470)
    at tools.jackson.databind.deser.jackson.BaseNodeDeserializer._handleDuplicateProperty(BaseNodeDeserializer.java:148)
    at ...GenericJacksonJsonRedisSerializer$TypeResolver.readTree(GenericJacksonJsonRedisSerializer.java:509)

Duplicate property names are valid JSON (RFC 8259) and occur in practice — for example in cache entries written by the Jackson 2 serializer, or by a polymorphic type whose @JsonTypeInfo(include = As.PROPERTY) type-id name coincides with a bean property of the same name (Jackson 2 emitted both as duplicate keys). Such entries can no longer be read back under the Jackson 3 serializer — not even to be evicted.

Reported in #3396, with a minimal reproduction there.

Fix

Bind the parser to the context before deserializing, so its stream-read capabilities are initialized. This mirrors how ObjectMapper._readTreeAndClose(...) binds the parser via assignAndReturnParser(...). The tree scan then applies Jackson's normal duplicate-property handling (last value wins) instead of dereferencing a null.

Test

GenericJacksonJsonRedisSerializerUnitTests.deserializeShouldHandleDuplicatePropertyWithDefaultTyping deserializes a value containing a duplicate property. It reproduces the NullPointerException above without the fix and passes with it.


  • I have read the Spring Data contribution guidelines.
  • There is a test case backing the change; no formatting-only changes are included.
  • I added myself as an author in the headers of the classes I touched.

Closes #3396

… properties.

GenericJacksonJsonRedisSerializer.TypeResolver.readTree(...) built the JSON node
tree using a DeserializationContext from ObjectMapper._deserializationContext()
that was never bound to the parser, so its stream-read capabilities stayed
uninitialized. Deserializing any value whose JSON contains a duplicate property
then failed with a NullPointerException in
BaseNodeDeserializer._handleDuplicateProperty, which consults
StreamReadCapability.DUPLICATE_PROPERTIES.

Duplicate property names are valid JSON (RFC 8259) and occur in practice, for
example in values written by the Jackson 2 serializer. Bind the parser to the
context (as ObjectMapper._readTreeAndClose does via assignAndReturnParser) so the
type-hint tree scan handles them.

Closes spring-projects#3396

Signed-off-by: Tomaz Cerar <tomaz@cerar.net>
@ctomc ctomc force-pushed the issue/gh-3396-typeresolver-npe branch from 96ed288 to 3f96d6e Compare July 10, 2026 13:25
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: waiting-for-triage An issue we've not yet triaged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GenericJacksonJsonRedisSerializer throws NullPointerException deserializing JSON with a duplicate property (Jackson 3, default typing)

2 participants