Skip to content

Allow BeanSerializerModifier to override property serializers - #6173

Open
hej090224 wants to merge 2 commits into
FasterXML:3.xfrom
hej090224:issue-4385-property-serializer
Open

Allow BeanSerializerModifier to override property serializers#6173
hej090224 wants to merge 2 commits into
FasterXML:3.xfrom
hej090224:issue-4385-property-serializer

Conversation

@hej090224

@hej090224 hej090224 commented Aug 25, 2026

Copy link
Copy Markdown

Summary

ValueSerializerModifier.changeProperties() (the 3.x equivalent of BeanSerializerModifier) receives BeanPropertyWriter instances after annotation-based serializers have already been assigned. The existing assignSerializer() guard rejects replacing those serializers, so a modifier cannot change one annotated property without copying the writer.

This change allows the existing public BeanPropertyWriter.assignSerializer() extension point to replace an existing non-null value serializer while continuing to reject clearing an assigned serializer with null. The separate assignNullSerializer() guard is unchanged, so a modifier can replace regular serialization while preserving an explicitly configured null serializer.

Rejecting null assignment preserves the _serializer/_dynamicSerializers invariant: writers with no statically assigned serializer own a dynamic lookup map, while writers with an assigned serializer do not.

No new public API is added. The change is binary compatible; the behavior of assignSerializer() changes only to permit intentional non-null replacement of an existing value serializer.

Tests

  • PropertySerializerModifier4385Test: verifies one of two same-type properties is replaced, annotation serializer precedence is changed only for the selected property, global/type serializers and other properties are unaffected, the annotation null serializer is preserved, and null assignment is rejected.
  • Related serializer, contextual, annotation, null-serializer, and unwrapped/view tests: 155 tests passed.
  • ./mvnw.cmd -B -ntp clean verify: 6,222 tests passed, 0 failures, 0 errors, 1 skipped.
  • ./mvnw.cmd -B -q -ff -ntp -DskipTests animal-sniffer:check: passed.
  • git diff --check: passed.

Fixes #4385

@Dongnyoung

Copy link
Copy Markdown
Contributor

The intended change seems to be serializer A -> serializer B, but removing the guard also enables serializer A -> null. For a writer constructed with a non-null serializer, _dynamicSerializers may remain null, so clearing the serializer could leave the writer in an invalid state when it later enters the dynamic lookup path. Would it be safer to allow non-null replacement while still rejecting null?

@hej090224

Copy link
Copy Markdown
Author

Thanks, this is a valid concern. I reproduced it on the previous head by having a serializer modifier call assignSerializer(null) for an annotated property with a non-final declared type. The writer then had _serializer == null and _dynamicSerializers == null; serialization entered the dynamic lookup path and failed with a NullPointerException, wrapped as a DatabindException.

I updated assignSerializer() to reject only the non-null-to-null transition, using the existing IllegalStateException guard convention. Non-null serializer replacement remains allowed, and no dynamic map initialization or new public API was added.

I also added a regression test for the rejected null assignment. The existing tests still cover non-null replacement and preservation of the annotation-provided null serializer. Verification passed with the focused tests, 155 related serializer/contextual/annotation/null/unwrapped/view tests, clean verify (6,222 tests, 0 failures, 0 errors, 1 skipped), animal-sniffer:check, and git diff --check.

The fix is pushed as commit c0bddaba1.

@gitar-bot

gitar-bot Bot commented Aug 25, 2026

Copy link
Copy Markdown
Code Review ✅ Approved

Allows BeanSerializerModifier to override property serializers by updating BeanPropertyWriter.assignSerializer to permit intentional replacement of existing value serializers. No issues found.

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

@github-actions

Copy link
Copy Markdown

🧪 Code Coverage Report

Metric Coverage Change
Instructions coverage 81.94% 📈 +0.030%
Branches branches 75.58% 📈 +0.020%

Coverage data generated from JaCoCo test results

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.

Allow changing serializer used for a single property of a Class

2 participants