基于反射的反序列化程序主动解析元数据

基于 System.Text.Json 反射的序列化程序以前使用延迟加载方法来解析属性元数据。 此方法使包含不受支持的属性类型的 POCO 能够成功反序列化,前提是基础 JSON 未绑定到任何不受支持的属性。 (尽管同一类型的实例无法 序列化。)

从 .NET 8 开始,序列化程序已更改,以便在序列化和反序列化中急切地解析所有属性。 此更改是为了更好地支持组合多个解析程序,这需要对序列化类型图进行早期分析。 此更改的副作用是,如果依赖于以前的行为,则会看到新的运行时反序列化错误。

旧行为

以下反序列化代码在 .NET 7 中会成功执行。

var result = JsonSerializer.Deserialize<MyPoco>("""{ "Value": 1 }"""); //, MyContext.Default.MyPoco);
Console.WriteLine(result.Value);

public class MyPoco
{
    public int Value { get; set; }

    public NestedValue Unsupported { get; set; }
}

public class NestedValue
{
    public ReadOnlySpan<byte> Span => Array.Empty<byte>();
}

新行为

从 .NET 8 开始,之前行为部分中的相同代码会在运行时引发 InvalidOperationException

System.InvalidOperationException:类型“NestedValue”上属性“Span”的类型“System.ReadOnlySpan”1[System.Byte] 对于序列化或反序列化无效,因为它是指针类型、是 ref 结构,或包含尚未由特定类型替换的泛型参数。

如果尝试序列化同一类型的实例,则此错误与在以前的版本中引发的错误一致。 它还与生成编译时错误的源生成器保持一致。

引入的版本

.NET 8 预览版 4

中断性变更的类型

此更改为行为更改

更改原因

与组合源生成的上下文中的快速路径序列化支持相关的新要求需要此更改(请参阅 dotnet/runtime#71933)。

如果此更改有问题,你可以:

  • 从类型中删除不受支持的属性。

  • 为不支持的类型创作自定义转换器。

  • 添加 JsonIgnoreAttribute 属性:

    public class MyPoco
    {
        public int Value { get; set; }
    
        [JsonIgnore]
        public NestedValue Unsupported { get; set; }
    }
    

受影响的 API