反序列化 JSON 仅当它为值类型 属性 指定值时

Deserialize JSON only if it specifies a value for a value type property

如果我有一个包含值类型属性的 DTO class,我如何才能惯用地使用 Newtonsoft 将 JSON 反序列化为我的 DTO class,同时确保 JSON定义值类型,可能包含该类型的 default 值?到目前为止,我看到的方法依赖于检查值是否为 default 值,但是,当 default 值也是 属性 的有效值时,这不是一个合适的解决方案.

例子

public class MyDto
{
    public bool MyProp { get; set; }
}
JSON Can deserialize to MyDto
{"MyProp": true} true
{"MyProp": false} true
{} false

当前解

目前我使用 System.ComponentModel.DataAnnotations.RequiredAttribute 并将类型声明为可为空,但这仅在模型绑定期间有效(而不是任何反序列化),并导致在引用 [= 时过度使用 ! 38=].

public class MyDto
{
    [Required]
    public bool? MyProp { get; set; }
}

我相信你要找的是 JsonPropertyAttribute Required 属性:

public class MyDto
{
    [JsonProperty(Required = Required.Always)]
    public bool MyProp { get; set; }
}

当被反序列化的 JSON 不包含指定的 属性 (MyProp) 时,这会导致异常。例如,以下内容:

string json = "{\"MyProp\": true}";
MyDto myDto = JsonConvert.DeserializeObject<MyDto>(json);
Console.WriteLine(myDto.MyProp);

json = "{\"MyProp\": false}";
myDto = JsonConvert.DeserializeObject<MyDto>(json);
Console.WriteLine(myDto.MyProp);

json = "{}";
myDto = JsonConvert.DeserializeObject<MyDto>(json);
Console.WriteLine(myDto.MyProp);

给出结果:

True
False
Run-time exception (line 17): Required property 'MyProp' not found in JSON. Path '', line 1, position 2.

您可以使用 JSON 架构 (Newtonsoft.Json.Schema) 验证 JSON,如下所示:

public class MyDto
{
    [JsonProperty(Required = Required.Always)]
    public bool MyProp { get; set; }
}


var generator = new JSchemaGenerator();
var schema = generator.Generate(typeof(MyDto));
var dto = JObject.Parse(@"{ 'MyProp': true }");
bool isValid = dto.IsValid(schema);
Console.WriteLine(isValid); // True

dto = JObject.Parse(@"{}");
isValid = dto.IsValid(schema);
Console.WriteLine(isValid); // False