缺少属性时如何强制 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 方法?