Add polymorphic serialization to System.Text.Json #54328
Closed
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.
Fixes #29937. Based on the prototype in #53882 which incorporates #30083. API design pending approval.
Infrastructural Changes
Here is a high-level overview of the infrastructural changes being made:
CanBePolymorphic
andCanUseDirectReadOrWrite
properties fromJsonConverter
have been moved toJsonTypeInfo
, since the value of these flags can now be influenced by user configuration or attributes.WriteStack
struct to support polymorphism:WriteStack.NextValueCanBePolymorphic
property which replacesJsonConverter.CanBePolymorphic
.ReferenceResolver.IgnoreCycles
implementation: the current implementation contains bespoke code to avoid polymorphic converters triggering false negatives. I have refactored the code slightly so that the cycle detection logic is combined with the polymorphic serialization infrastructure.Potential breaking change
The changes isolated in b14bcdf introduce a deliberate breaking change when it comes to the handling of
new object()
values. The existing implementation will hardcode the serialization to{}
even if the user has subscribed a customJsonConverter<object>
that does something different. I would like to change this behavior for a few reasons:new object()
values. Users cannot specify a custom serialization format fornew object()
values.object
instance serialization to the relevant converter.new object()
instances are being serialized in production applications.The breaking change concerns the following scenario:
In .NET 5 the above would print
{}
, however under the new changes it would print42
. This could break users with custom object converters who rely on the existing hardcoding behavior.Performance
When benchmarked against
main
using statistical testing with 5% threshold, performance of the feature branch is largely equivalent. It should be noted however that certain polymorphism-heavy scenaria (e.g.WriteJson<ArrayList>
) do record a slight regression (which can be observed when applying thresholds < 3%). After profiling the code I can confirm that this regression is in part attributable to the additional work required by computing theWriteStack.NextValueCanBePolymorphic
property.