调用JsonConvert.DeserializeObject()时对象丢失数据的问题排查
问题原因分析
这个问题的核心是Newtonsoft.Json在使用标记了[JsonConstructor]的构造函数反序列化时,没有正确将JSON属性绑定到构造函数的参数上,导致PartNumber属性没有被赋值。
具体来说:
- 你的
Part类属性的setter是private的,所以Newtonsoft.Json无法直接通过反射设置属性值,只能依赖你定义的带[JsonConstructor]的构造函数来初始化对象。 - 虽然构造函数的参数名(如
partNumber)和JSON的属性名(PartNumber)只是大小写差异,Newtonsoft.Json默认支持大小写不敏感匹配,但你同时使用了[DataMember]标记(这是给DataContractSerializer用的),这干扰了Newtonsoft.Json的默认匹配逻辑,导致参数partNumber没有正确获取到JSON中PartNumber的值。
解决方案
这里有几个可行的解决办法,你可以根据自己的代码设计选择:
方案1:给构造函数参数添加[JsonProperty]标记
明确指定每个构造函数参数对应的JSON属性名,消除匹配歧义:
[JsonConstructor] public Part( [JsonProperty("WorkOrder")] string workOrder, [JsonProperty("PartNumber")] string partNumber, [JsonProperty("Revision")] string revision, [JsonProperty("PartName")] string partName, [JsonProperty("SerialNumber")] string serialNumber ) { WorkOrder = workOrder; PartNumber = partNumber; Revision = revision; PartName = partName; SerialNumber = serialNumber; }
方案2:让Newtonsoft.Json识别[DataMember]标记
配置JsonSerializerSettings使用DataContractResolver,这样Newtonsoft.Json会遵循[DataMember]的标记来匹配属性:
Part p = JsonConvert.DeserializeObject<Part>(sqlcommand.ExecuteScalar().ToString(), new JsonSerializerSettings { ContractResolver = new DataContractResolver() });
方案3:修改属性setter为public(如果设计允许)
如果不需要保持setter的私有性,直接把setter改成public,去掉[JsonConstructor],Newtonsoft.Json会直接设置属性值:
[DataMember] public string PartNumber { get; set; } [DataMember] public string PartName { get; set; } // 其他属性同理修改setter
验证
修改后重新运行代码,你会发现PartNumber属性能正确获取到JSON中的值,GetPartNumber()也会输出预期的20584。
内容的提问来源于stack exchange,提问作者kryz
相关产品推荐
相关产品推荐

