缺少 属性 时如何强制 System.Text.Json 序列化程序抛出异常?

How to force System.Text.Json serializer throw exception when property is missing?

Json.NET 行为可以由属性定义:如果 json 有效载荷不包含必需的 属性.

,要么使用默认值,要么只抛出异常

然而 System.Text.Json 序列化程序静静地什么都不做。
有 class:

public sealed class Foo
{
    [Required]
    public int Prop {get;set;} = 10;
}

并反序列化空对象:

JsonSerializer.Deserialize<Foo>("{}");

我只是得到一个 FooProp=10 的实例。 我在 JsonSerializerOptions 中找不到任何设置来强制它抛出异常。可能吗?

如果未收到目标类型的某个属性的值,

System.Text.Json 不会引发异常。您需要实现自定义转换器。

参考:https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to#required-properties

System.Text.Json 不能完全替代 Json.NET。它是为速度而构建的,考虑到最少的分配,而不是功能的完整性。如果你想要验证,你可以

  1. 使用Json.NET
  2. 使用 Validator class
  3. 序列化后验证对象
  4. 创建自定义转换器

TheGeneral 展示了如何执行 #3。自定义验证器必须显式处理 所有 验证和 return 一些有意义的异常。如果只有一个 属性 需要检查,那么抛出一个 ArgumentNullException 就足够了。验证多个属性需要更复杂的东西,例如 ValidationException 来包含验证结果。

K。 Scott Allen 的文章 Manual Validation with Data Annotations 展示了如何执行 #2。

一个选项是使用 Validator.ValidateObject 来验证一个对象并得到一个包含所有失败验证的 ValidationException :

try
{
    var validationCtx=new ValidationContexgt(myFoo);
    Validator.ValidateObject(myFoo,validationCtx);
}
catch(ValidatinException ex)
{
    //Do something with the results.
}

如果无效对象很少见,这是可以的,因为抛出异常是昂贵的。也许更好的选择是使用 Validator.TryValidateObject :

var results = new List<ValidationResult>();
var validationCtx=new ValidationContexgt(myFoo);
if(Validator.TryValidateObject(myFoo,validationCtx,results))
{
    //Use the object
}
else
{
    //Do something with the failed results
}

您只需设置 MissingMemberHandling 即可,它会为您处理一切,但您需要安装 DevBetter.JsonExtensions MissingMemberHandling.Ignore 和 MissingMemberHandling.Error

var deserializeOptions = new JsonSerializerOptions()
    .SetMissingMemberHandling(MissingMemberHandling.Ignore);

var weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString, deserializeOptions);