对象类型的多态序列化

利用默认配置,System.Text.Json使用多形性序列化 object 类型的值。 如果注册 object 的自定义转换器,则此行为不一致。 System.Text.Json 具有对根级对象值进行多形性硬编码的历史记录,而对嵌套对象值则没有。 从 .NET 7 开始,此行为已更改,以便自定义转换器不再使用多形性。

旧行为

请考虑以下自定义对象转换器:

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 NotImplementedException();
}

在以前的版本中,以下代码序列化为 0。 这是因为序列化程序使用了多形性而忽略了自定义转换器。

var options = new JsonSerializerOptions { Converters = { new CustomObjectConverter() } };
JsonSerializer.Serialize<object>(0, options);

但是,以下代码序列化为 42,因为序列化程序遵循自定义转换器。

var options = new JsonSerializerOptions { Converters = { new CustomObjectConverter() } };
JsonSerializer.Serialize<object[]>(new object[] { 0 }, options);

新行为

从 .NET 7 开始,使用在上一行为部分中定义的自定义对象转换器,以下代码序列化为 42。 这是因为序列化程序将始终咨询自定义转换器,而不使用多形性。

var options = new JsonSerializerOptions { Converters = { new CustomObjectConverter() } };
JsonSerializer.Serialize<object>(0, options);

引入的版本

.NET 7

中断性变更的类型

此项更改可能会影响二进制兼容性

更改原因

由于某一类型的序列化协定不一致,因此进行了这种更改,具体取决于这是作为根级值还是嵌套值进行序列化。

如果需要,可以通过调用非类型化序列化方法之一来获取根级值的多形性:

var options = new JsonSerializerOptions { Converters = { new CustomObjectConverter() } };
JsonSerializer.Serialize(0, inputType: typeof(int), options); // Serializes as 0.

受影响的 API