C# 反序列化记录-如何初始化缺少的属性

C# 反序列化记录-如何初始化缺少的属性,c#,json.net,record,C#,Json.net,Record,考虑一个简单的例子,尝试反序列化缺少某些属性的记录: #nullable enable record Rec(int Age, Employee Employee); // Employee has a default constructor var rec = JsonConvert.DeserializeObject<Rec>("{\"Age\":30}"); #可空启用 记录记录(年龄,员工);//Employee有一个默认构造函数

考虑一个简单的例子,尝试反序列化缺少某些属性的记录:

#nullable enable

record Rec(int Age, Employee Employee); // Employee has a default constructor

var rec = JsonConvert.DeserializeObject<Rec>("{\"Age\":30}");
#可空启用
记录记录(年龄,员工);//Employee有一个默认构造函数
var rec=JsonConvert.DeserializeObject(“{\'年龄\':30}”);
我得到
rec
,Employee设置为null而没有任何编译器警告,尽管启用了
nullable
,但必须使用默认构造函数手动设置它

有没有办法告诉
反序列化对象
尝试/使用默认构造函数来处理缺少的属性,而不是将它们设置为null?

有一种方法允许您传入一个
JsonConverter
数组,它允许您自己管理类型转换(来自JObject)。或者,您也可以将默认的
JsonSerializerSettings
更改为NOTallow null,并手动处理引发的异常

所有这些都需要大量样板代码,但对于简单的默认类型实例化,您可以从中继承
CustomCreationConverter

类似的规则适用于C#9
record
,但是
反序列化对象
将调用与JSON字符串中可用参数匹配的相关构造函数,因此您可以使用详细声明语法来实现相同的目的:

record Rec
{
    public int Age { get;init; }
    public Employee Employee { get;init; } = new Employee();
}

请参阅此提琴:

不要求为空?您可能需要自己解释一下,先生,这是因为设计模式可能会导致在许多级别上需要一些有趣的解决方法……我的意思是,使用#nullable enable,我希望在没有编译器警告的情况下,不会将Employee设为null,而在这种情况下,我没有得到编译器警告。但是,是的,我正在编辑我的问题。我打算提供一个答案,类是有办法的,但我不确定记录和反序列化所涉及的语义。@chrischaller上面的记录将只包含一个构造函数
RecRec(int-Age,Employee-Employee){thisd.Age=Age;this.Employee=Employee;}
我认为您必须使用详细语法,这样您就可以声明默认实现,但还没有测试它。好的,很好,但是如果您看我的问题,我想知道是否有方法在调用反序列化对象时指定它?我看到了,立即畏缩。。。您必须编写自己的
JsonConvert
实现,这将是大量的代码,并在某种程度上挫败了使用记录来减少和简化不可变classI的语法这一点。我发布了此功能请求-不,您没有抓住要点,记录的默认状态应该是记录定义的一部分,或管理序列化的自定义代码的一部分,而不是已提供必要机制的序列化管道的特殊通用功能。对于记录来说,这并不是什么特别或新的事情,同样的事情也适用于类。我会立即投票反对以某种方式将其添加为序列化的通用方面,因为它会破坏或对太多现有实现产生不利影响,我所有的应用程序都会突然开始在placeauto属性中填充新的空记录,并使用默认的初始值设定项,这意味着你提到的那些问题几乎不再存在。我祝你旅途顺利,但听起来你好像在倒退,或者至少是真的很艰难。
public class Rec
{
    public int Age { get;set; }
    public Employee Employee { get;set; } = new Employee();
}
record Rec
{
    public int Age { get;init; }
    public Employee Employee { get;init; } = new Employee();
}