-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Add polymorphic serialization to System.Text.Json #54328
Add polymorphic serialization to System.Text.Json #54328
Conversation
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
Tagging subscribers to this area: @eiriktsarpalis, @layomia Issue DetailsFixes #29937. Based on the prototype in #53882 which incorporates #30083. API design pending API review. Infrastructural ChangesHere is a high-level overview of the infrastructural changes being made:
Potential breaking changeThe changes isolated in b14bcdf introduce a deliberate breaking change when it comes to the handling of
The breaking change concerns the following scenario: using System;
using System.Text.Json;
using System.Text.Json.Serialization;
var options = new JsonSerializerOptions { Converters = { new CustomObjectConverter() } };
string json = JsonSerializer.Serialize(new object(), options);
Console.WriteLine(json);
public class CustomObjectConverter : JsonConverter<object>
{
public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) => writer.WriteNumberValue(42);
public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => throw new NotSupportedException();
} In .NET 5 the above would print PerformanceWhen benchmarked against
|
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.