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

Posted

技术标签:

【中文标题】缺少属性时如何强制 System.Text.Json 序列化程序抛出异常?【英文标题】:How to force System.Text.Json serializer throw exception when property is missing? 【发布时间】: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的第二个选项 【参考方案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。它是为速度而构建的,考虑到最少的分配,而不是功能的完整性。如果你想要验证,你可以

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

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);

【讨论】:

以上是关于缺少属性时如何强制 System.Text.Json 序列化程序抛出异常?的主要内容,如果未能解决你的问题,请参考以下文章

如何强制杰克逊在控制器中调用对象(dto)中所有属性的 Set 方法?

在空手道框架中实施摘要认证时面临问题;响应:缺少强制摘要值

在编译时,我得到“错误:不同指针类型 'char*' 和 'char (*)[200]' 之间的比较缺少强制转换”在线

Maven 强制插件缺少或无效规则

VCF 文件缺少强制性标题行(“#CHROM...”)

AngularJS:如何在为缺少的属性提供默认值时避免非分配错误?