-
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
System.Text.Json uses inconsistent polymorphism semantics with custom object
converters
#72681
Comments
Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis Issue DetailsSystem.Text.Json hardcodes polymorphic serialization when serializing root-level values of type using System;
using System.Text.Json;
using System.Text.Json.Serialization;
var options = new JsonSerializerOptions { Converters = { new CustomObjectConverter() } };
Console.WriteLine(JsonSerializer.Serialize<object>(0, options)); // Prints 0, custom converter not honored
Console.WriteLine(JsonSerializer.Serialize<object[]>(new object[] { 0 }, options)); // Prints [42], custom converter honored
public class CustomObjectConverter : JsonConverter<object>
{
public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
{
if (value is int)
{
writer.WriteNumberValue(42);
}
else
{
JsonSerializer.Serialize(writer, value, value.GetType(), options);
}
}
public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
=> throw new NotImplementedException();
} This issue proposes that we change the root-level behavior for custom This change might be a breaking change for users that rely on the current behavior. As a workaround, users can get back the existing polymorphic behavior by calling into one of the untyped -JsonSerializer.Serialize<object?>(value, options);
+Type runtimeType = value?.GetType() ?? typeof(object);
+JsonSerializer.Serialize(value, runtimeType, options);
|
Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis Issue DetailsSystem.Text.Json hardcodes polymorphic serialization when serializing root-level values of type using System;
using System.Text.Json;
using System.Text.Json.Serialization;
var options = new JsonSerializerOptions { Converters = { new CustomObjectConverter() } };
Console.WriteLine(JsonSerializer.Serialize<object>(0, options)); // Prints 0, custom converter not honored
Console.WriteLine(JsonSerializer.Serialize<object[]>(new object[] { 0 }, options)); // Prints [42], custom converter honored
public class CustomObjectConverter : JsonConverter<object>
{
public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
{
if (value is int)
{
writer.WriteNumberValue(42);
}
else
{
JsonSerializer.Serialize(writer, value, value.GetType(), options);
}
}
public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
=> throw new NotImplementedException();
} This issue proposes that we change the root-level behavior for custom This change might be a breaking change for users that rely on the current behavior. As a workaround, users can get back the existing polymorphic behavior by calling into one of the untyped -JsonSerializer.Serialize<object?>(value, options);
+Type runtimeType = value?.GetType() ?? typeof(object);
+JsonSerializer.Serialize(value, runtimeType, options);
|
Fixed in #72789. |
System.Text.Json hardcodes polymorphic serialization when serializing root-level values of type
object
, regardless of whether the registeredJsonConverter<object>
supports polymorphism. While this is consistent with the semantics of the built-in converter forobject
, it can result in inconsistent serialization contracts when used in conjunction with custom converters, depending on whether the value is serialized at the root level or as a nested node:This issue proposes that we change the root-level behavior for custom
object
converters so that it no longer defaults to polymorphism (unless a polymorphic converter is being used). This will make serialization contracts consistent, regardless of whether the instance is serialized as a root-level value or as a nested value.This change might be a breaking change for users that rely on the current behavior. As a workaround, users can get back the existing polymorphic behavior by calling into one of the untyped
JsonSerializer
APIs, explicitly passing the runtime type of the value as theinputType
parameter:Related to #54436 and #72187.
The text was updated successfully, but these errors were encountered: