如何用Newtonsoft.Json实现C# Record默认参数反序列化同System.Text.Json效果?
解决Newtonsoft.Json反序列化C# Record时默认值不生效的问题
问题背景
我们有一个C# Record,最初仅定义了int no参数,后续迭代新增了带默认值的paramStr参数,定义如下:
record SimpleRecord(int no, string paramStr = "New param that did not existed");
当用仅包含no字段的旧JSON反序列化时:
string jsonText = "{\"no\":10}"; SimpleRecord? parsedJson1 = System.Text.Json.JsonSerializer.Deserialize<SimpleRecord>(jsonText); SimpleRecord? parsedJson2 = Newtonsoft.Json.JsonConvert.DeserializeObject<SimpleRecord>(jsonText);
System.Text.Json能正确为paramStr赋予默认值,但Newtonsoft.Json得到的paramStr为null。现有项目基于Newtonsoft.Json,不想重构,需要实现与System.Text.Json一致的反序列化效果。
解决方案
方法1:给参数添加特性指定默认值处理
直接在Record的paramStr参数上添加[JsonProperty]和[DefaultValue]特性,配置默认值填充规则:
record SimpleRecord( int no, [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] [DefaultValue("New param that did not existed")] string paramStr = "New param that did not existed" );
这样Newtonsoft.Json在反序列化时,会自动为缺失的paramStr字段填充指定的默认值。
方法2:自定义ContractResolver全局配置
如果不想逐个修改Record,可以自定义一个ContractResolver,让它自动识别Record可选参数的默认值并应用填充:
public class RecordDefaultValueContractResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { JsonProperty property = base.CreateProperty(member, memberSerialization); // 检查当前属性是否属于Record类型,且对应构造参数有默认值 if (member is PropertyInfo prop && prop.DeclaringType.IsRecord()) { var ctor = prop.DeclaringType.GetConstructors() .FirstOrDefault(c => c.GetParameters().Any(p => p.Name.Equals(prop.Name, StringComparison.OrdinalIgnoreCase))); var param = ctor?.GetParameters().FirstOrDefault(p => p.Name.Equals(prop.Name, StringComparison.OrdinalIgnoreCase)); if (param != null && param.HasDefaultValue) { property.DefaultValue = param.DefaultValue; property.DefaultValueHandling = DefaultValueHandling.Populate; } } return property; } }
使用时,在反序列化配置中指定这个Resolver:
var settings = new JsonSerializerSettings { ContractResolver = new RecordDefaultValueContractResolver() }; SimpleRecord? parsedJson2 = JsonConvert.DeserializeObject<SimpleRecord>(jsonText, settings);
也可以设置为全局默认配置,避免每次反序列化都重复指定:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings { ContractResolver = new RecordDefaultValueContractResolver() };
方法3:显式指定构造器(单个Record场景)
对于单个Record,也可以显式定义构造器,确保Newtonsoft.Json在反序列化时使用带默认值的参数:
record SimpleRecord { public int No { get; init; } public string ParamStr { get; init; } public SimpleRecord(int no, string paramStr = "New param that did not existed") { No = no; ParamStr = paramStr; } }
这种方式需要把Record从位置参数语法改为显式属性+构造器的形式,适合不需要大量修改的场景。
内容的提问来源于stack exchange,提问作者Audrius Gailius
相关产品推荐
相关产品推荐

