对象类型的多态序列化
利用默认配置,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
- System.Text.Json.JsonSerializer.Serialize<TValue>(TValue, JsonSerializerOptions)
- System.Text.Json.JsonSerializer.Serialize<TValue>(Stream, TValue, JsonSerializerOptions)
- System.Text.Json.JsonSerializer.Serialize<TValue>(Utf8JsonWriter, TValue, JsonSerializerOptions)
- System.Text.Json.JsonSerializer.SerializeAsync<TValue>(Stream, TValue, JsonSerializerOptions, CancellationToken)