-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Fix duplicate serialization of virtual properties with JsonPropertyName on base class #122842
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…me on base class When a virtual property with [JsonPropertyName] on the base class is overridden in a derived class without the attribute, the property was being serialized twice with different JSON names (once from base class's attribute, once from derived class). The fix tracks virtual properties by their CLR member name during property resolution, so that when processing base class properties, we can detect if they have already been overridden by a derived class property - even when the JSON property names differ. This affects both the runtime (DefaultJsonTypeInfoResolver) and the source generator (JsonSourceGenerator). Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
|
Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes a bug where virtual properties with [JsonPropertyName] on a base class were serialized twice when overridden in a derived class without the attribute. The root cause was that property conflict resolution only tracked properties by JSON name, so when the derived override lacked the attribute, the different JSON names ("Id" vs "test") prevented collision detection.
Key Changes
- Added
OverriddenVirtualPropertiesdictionary to track virtual properties by CLR member name - Added early-exit check in
AddPropertyWithConflictResolutionto detect virtual property overrides even when JSON names differ - Applied the same fix to both runtime (JsonTypeInfo.cs) and source generator (JsonSourceGenerator.Parser.cs)
- Set
IsVirtualproperty inCreatePropertyInfoCorefor source-generated metadata - Added comprehensive tests covering the bug scenario and related edge cases
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs | Added OverriddenVirtualProperties dictionary to PropertyHierarchyResolutionState and implemented virtual property override detection logic in AddPropertyWithConflictResolution |
| src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs | Mirrored the runtime changes in the source generator: added OverriddenVirtualMembers dictionary and override detection logic |
| src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Helpers.cs | Set IsVirtual property in CreatePropertyInfoCore to ensure source-generated metadata has this flag set correctly |
| src/libraries/System.Text.Json/tests/Common/PropertyNameTests.cs | Added three test methods covering virtual property scenarios and test class definitions |
| src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyNameTests.cs | Registered new test classes in both Metadata and Default source generation contexts |
| [Fact] | ||
| public async Task VirtualPropertyWithJsonPropertyNameOnBaseClass_SerializedOnce() | ||
| { | ||
| // Regression test for https://github.com/dotnet/runtime/issues/96998 |
Copilot
AI
Jan 4, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
andreanadr
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added new email
andreanadr
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added new email
andreanadr
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added new email
andreanadr
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added new email
Description
Virtual properties with
[JsonPropertyName]on base class were serialized twice when overridden in derived class without the attribute:Root cause: Property conflict resolution tracked properties by JSON name only. When derived class overrides without inheriting the attribute, names differ (
"Id"vs"test"), so no collision detected.Fix:
OverriddenVirtualPropertiesdictionary toPropertyHierarchyResolutionStateto track virtual properties by CLR member nameJsonSourceGenerator.Parser.cs)IsVirtualproperty inCreatePropertyInfoCorefor source-generated metadataCustomer Impact
Properties serialized multiple times with different keys, causing invalid/unexpected JSON output and potential deserialization failures.
Regression
No. Issue existed since initial version per reporter.
Testing
Risk
Low. Change is targeted to virtual property override detection during property hierarchy resolution. Existing conflict resolution logic unchanged.
Package authoring no longer needed in .NET 9
IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older versions.
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.