如何使用System.Text.Json处理可为null的引用类型? 我已经把我的项目升级到了磊科3,我正在重构一个项目来使用新的空引用类型特征,但是由于下面的问题,它很快就被卡住了。
假设我使用一个REST api,它返回以下JSON:如何使用System.Text.Json处理可为null的引用类型? 我已经把我的项目升级到了磊科3,我正在重构一个项目来使用新的空引用类型特征,但是由于下面的问题,它很快就被卡住了。,json,.net-core-3.0,nullable-reference-types,system.text.json,Json,.net Core 3.0,Nullable Reference Types,System.text.json,假设我使用一个REST api,它返回以下JSON: { "Name": "Volvo 240", "Year": 1989 } 此api始终返回名称/年份,因此它们不可为空 我将使用这个简单的类进行反序列化: 公车 { 公共字符串名称{get;set;} 公共整数年{get;set;} } 我将使用新的System.Text.Json var car=JsonSerializer.Deserialize(json); 这一切都是可行的,但是当启用可为null的引用类型时,我在Ca
{
"Name": "Volvo 240",
"Year": 1989
}
此api始终返回名称/年份,因此它们不可为空
我将使用这个简单的类进行反序列化:
公车
{
公共字符串名称{get;set;}
公共整数年{get;set;}
}
我将使用新的System.Text.Json
var car=JsonSerializer.Deserialize(json);
这一切都是可行的,但是当启用可为null的引用类型时,我在Car
类中得到一个警告,该警告声明为不可为null,但可以为null。我理解为什么会得到这个结果,因为可以在不初始化Name
属性的情况下实例化这个对象
因此理想情况下,Car
应如下所示:
公车
{
公共字符串名称{get;}
公共整数年{get;}
公共汽车(字符串名称,整数年)
{
名称=名称;
年=年;
}
}
但这不起作用,因为System.Text.Json
序列化程序不支持带参数的构造函数
所以我的问题是:我如何声明Car
,使Name
不可为空,并使其在System.Text.Json
中工作,而不得到“不可为空”的警告`
我不想使其可为null,因为在启用可为null的引用类型时,我必须对基本上所有内容进行null检查,并且因为我的示例中的REST API表示始终提供这些类型,所以它们不应为null。更新 .NET5的
System.Text.Json
for.NET5现在支持参数化构造函数,因此这应该不再是一个问题
看
下面的旧答案
读了这本书之后,我发现了如何解决这个问题
因此,除非System.Text.Json
无法使用构造函数中的参数实例化类,否则Car
类必须如下所示:
公车
{
公共字符串名称{get;set;}=default!;
公共整数年{get;set;}
}
更新
如果您在net5
,请使用@langen指出的参数化构造函数支持。下面的其他方法仍然有用
原创
略为另类的方法System.Text.Json
使用私有无参数构造函数似乎没有问题。因此,您至少可以执行以下操作:
公车
{
公共字符串名称{get;set;}
公共整数年{get;set;}
//仅适用于System.Text.Json反序列化
#pragma warning disable CS8618//不可为空的字段未初始化。
私家车(){}
#pragma警告恢复CS8618
公共汽车(字符串名称,整数年)
{
名称=名称;
年=年;
}
}
好处是:
- 来自您自己代码的对象的Init必须通过公共构造函数
- 您不需要执行
=null每个属性上的代码>
- Json仍然需要属性上的setter在反序列化期间实际设置值。我试过使用私有对象,但这是不可能的,所以我们仍然无法得到一个不变的对象
使用系统;
公车
{
私有字符串?名称;
私人国际年;
公共字符串名
{
get=>this.name??抛出新的invalidoOperationException($“{nameof(this.name)}未设置。”);
set=>this.name=value;
}
公共国际年
{
get=>this.year??抛出新的InvalidOperationException($“{nameof(this.year)}未设置。”);
set=>this.year=值;
}
}
就个人而言,我宁愿使用=”代码>,否则您基本上是在说(在我看来)“这个属性永远不会为null(只是开玩笑)”。或者使用JSON.NET。System.Text.Json还不是完全的替代品。至于=默认值
。。。还没有。当我在2019年10月读到这篇文章时,我认为您正在将其设置为null代码>。也许明年吧。这与微软推荐的实体对象类似。EF团队实际上建议使用null
作为一种说法,“我知道这永远不会是null
”,尽管我喜欢这种可空性的潜力,但这确实让人感觉有点不舒服。…。@LasseV.Karlsen注意,在asp.net的上下文中,添加=null
实际上是在请求对象上修饰所需属性的正确方法。它是[Required]
属性的后续项。添加=null
将简单地告诉编译器您知道自己在做什么,它将不允许将字符串反序列化为null。由于字符串不可为空,asp.net将拒绝未为不可为空/必需的引用类型指定值的任何请求。请注意,执行#nullable disable
实际上会禁用空限制——所以不要这样做@MattJacobiSystem.Text.Json
将愉快地将null
反序列化为不可为null的字符串属性;至少在默认情况下,不管反序列化类(我刚刚尝试过)的状态如何,是否有一些选项触发这种更严格的“我真的是指可空性”模式?