【问题标题】:How to force System.Text.Json serializer throw exception when property is missing?缺少属性时如何强制 System.Text.Json 序列化程序抛出异常?
【发布时间】:2020-10-15 14:30:19
【问题描述】:

Json.NET 行为可以由属性定义:使用默认值,或者如果 json 有效负载不包含所需属性,则仅抛出异常。

然而,System.Text.Json 序列化程序默默地什么也不做。
上课:

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

并反序列化空对象:

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

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

【问题讨论】:

  • 根据required properties你应该创建自定义转换器
  • System.Text.Json 不是 Json.NET 的完全替代品。它是为速度而构建的,考虑到最小的分配,而不是功能的完整性。如果您想要验证,您可以 1) 使用 Json.NET 2) 使用 Validator 类验证对象之后 序列化或 3) 创建自定义转换器
  • 检查Manual Validation with Data Annotations的第二个选项

标签: c# json .net-core system.text.json


【解决方案1】:

如果没有接收到目标类型的属性之一的值,System.Text.Json 不会引发异常。您需要实现一个自定义转换器。

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

【讨论】:

    【解决方案2】:

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

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

    TheGeneral 展示了如何做#3。自定义验证器必须显式处理 all 验证并返回一些有意义的异常。如果只有一个属性要检查,则抛出 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
    }
    

    【讨论】:

    • 验证的问题是默认实例可能是绝对有效的,但是在验证的时候我们不知道payload是否正确。
    【解决方案3】:

    您只需执行 SetMissingMemberHandling,它会为您处理所有事情,但您需要安装 DevBetter.JsonExtensions MissingMemberHandling.Ignore 和 MissingMemberHandling.Error

    var deserializeOptions = new JsonSerializerOptions()
        .SetMissingMemberHandling(MissingMemberHandling.Ignore);
    
    var weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString, deserializeOptions);
    

    【讨论】:

      猜你喜欢
      • 2013-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-14
      • 1970-01-01
      • 2015-08-23
      • 2021-10-19
      相关资源
      最近更新 更多