必需的属性
可以标记某些属性,用于指示其必须存在于 JSON 有效负载中,反序列化才能成功。 同样,可以设置一个选项,来指定 JSON 有效负载中存在所有非可选构造函数参数。 如果其中一个或多个所需的属性不存在,JsonSerializer.Deserialize 方法将引发一个 JsonException。
有三种方法可以标记 JSON 反序列化所需的属性或字段:
- 通过添加
required
修饰符。 - 通过使用 JsonRequiredAttribute 进行批注。
- 通过修改协定模型的 JsonPropertyInfo.IsRequired 属性。
若要指定 JSON 反序列化所需的所有非可选构造函数参数,请将 JsonSerializerOptions.RespectRequiredConstructorParameters 选项(或者,对于源代码生成,将 RespectRequiredConstructorParameters 属性)设置为 true
。 有关详细信息,请参阅非可选构造函数参数部分。
从序列化程序的角度来看,C# required
修饰符和 [JsonRequired]
属性是等效的,两者都映射到同一元数据,即 JsonPropertyInfo.IsRequired。 大多数情况下,只需使用内置的 C# 关键字即可。 但是,在以下情况中,应改用 JsonRequiredAttribute:
- 如果你使用的是 C# 以外的编程语言或 C# 的低级版本。
- 如果只想将要求应用于 JSON 反序列化。
- 如果在源生成模式下使用
System.Text.Json
序列化。 在这种情况下,如果使用required
修饰符,代码不会编译,因为源生成是在编译时发生的。
以下代码片段显示使用 required
关键字修改过的属性示例。 JSON 有效负载中必须有此属性,反序列化才能成功。
public static void RunIt()
{
// 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:
public static void RunIt()
{
// 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 属性,通过协定模型来控制是否需要某个属性:
public static void RunIt()
{
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 succeeds even though
// the Name property isn't in the JSON payload.
JsonSerializer.Deserialize<Person>("""{"Age": 42}""", options);
}
public class Person
{
public required string Name { get; set; }
public int Age { get; set; }
}
非可选构造函数参数
在 .NET 9 之前,基于构造函数的反序列化将所有构造函数参数视为可选参数,如以下示例所示:
var result = JsonSerializer.Deserialize<Person>("{}");
Console.WriteLine(result); // Person { Name = , Age = 0 }
record Person(string Name, int Age);
从 .NET 9 开始,可以设置 RespectRequiredConstructorParameters 标志,以根据需要处理非可选构造函数参数。
public static void RunIt()
{
JsonSerializerOptions options = new()
{
RespectRequiredConstructorParameters = true
};
string json = """{"Age": 42}""";
// The following line throws a JsonException at run time.
JsonSerializer.Deserialize<Person>(json, options);
}
record Person(string Name, int? Age = null);
功能开关
可以使用 System.Text.Json.Serialization.RespectRequiredConstructorParametersDefault
功能开关全局打开 RespectRequiredConstructorParameters
设置。 将以下 MSBuild 项添加到项目文件(例如,.csproj 文件):
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Text.Json.Serialization.RespectRequiredConstructorParametersDefault" Value="true" />
</ItemGroup>
RespectRequiredConstructorParametersDefault
API 在 .NET 9 中作为选择加入标志实现,以避免中断现有应用程序。 如果要编写新应用程序,强烈建议在代码中启用此标志。