必需的属性

从 .NET 7 开始,可以标记某些属性,用于指示其必须存在于 JSON 有效负载中,反序列化才能成功。 如果其中一个或多个所需的属性不存在,JsonSerializer.Deserialize 方法将引发一个 JsonException

有三种方法可以标记 JSON 反序列化所需的属性或字段:

从序列化程序的角度来看,这两个分界是等效的,并且均映射到同一元数据片段,即 JsonPropertyInfo.IsRequired。 大多数情况下,只需使用内置的 C# 关键字即可。 但是,在以下情况中,应改用 JsonRequiredAttribute

  • 如果你使用的是 C# 以外的编程语言或 C# 的低级版本。
  • 如果只想将要求应用于 JSON 反序列化。
  • 如果在源生成模式下使用 System.Text.Json 序列化。 在这种情况下,如果使用 required 修饰符,代码不会编译,因为源生成是在编译时发生的。

以下代码片段显示使用 required 关键字修改过的属性示例。 JSON 有效负载中必须有此属性,反序列化才能成功。

using System.Text.Json;

// The following line throws a JsonException at run time.
Console.WriteLine(JsonSerializer.Deserialize<Person>("""{"Age": 42}"""));

public class Person
{
    public required string Name { get; set; }
    public int Age { get; set; }
}

也可使用 JsonRequiredAttribute

using System.Text.Json;

// The following line throws a JsonException at run time.
Console.WriteLine(JsonSerializer.Deserialize<Person>("""{"Age": 42}"""));

public class Person
{
    [JsonRequired]
    public string Name { get; set; }
    public int Age { get; set; }
}

还可以使用 JsonPropertyInfo.IsRequired 属性,通过协定模型来控制是否需要某个属性:

var options = new JsonSerializerOptions
{
    TypeInfoResolver = new DefaultJsonTypeInfoResolver
    {
        Modifiers =
        {
            static typeInfo =>
            {
                if (typeInfo.Kind != JsonTypeInfoKind.Object)
                    return;

                foreach (JsonPropertyInfo propertyInfo in typeInfo.Properties)
                {
                    // Strip IsRequired constraint from every property.
                    propertyInfo.IsRequired = false;
                }
            }
        }
    }
};

// Deserialization now succeeds even though the Name property isn't in the JSON payload.
JsonSerializer.Deserialize<Person>("""{"Age": 42}""", options);