使用Newtonsoft.Json,如何保证依赖属性的反序列化顺序?
解决Newtonsoft.Json反序列化时属性依赖顺序问题
问题核心
反序列化时SecondVal的setter依赖FirstVal,但默认情况下Newtonsoft.Json不一定按预期顺序赋值,导致FirstVal还是默认值时就执行SecondVal的setter,计算出错。用JsonProperty(Order)无效的话,可以试试以下方案:
方案1:用[OnDeserialized]特性延迟计算(推荐)
通过临时字段接收JSON中的SecondVal值,等所有属性反序列化完成后,再用已赋值的FirstVal计算最终的secondVal:
public class MyClass { private int secondVal; // 接收JSON里的SecondVal原始值,不对外暴露 [JsonProperty("SecondVal")] private int _secondValTemp; public int FirstVal { get; set; } public int SecondVal { get => secondVal + FirstVal; private set => secondVal = value - FirstVal; } // 反序列化完成后自动执行 [OnDeserialized] private void OnDeserialized(StreamingContext context) { secondVal = _secondValTemp - FirstVal; } }
这个方法不依赖JSON中属性的顺序,不管FirstVal和SecondVal在JSON里谁在前,反序列化完成后FirstVal肯定有值,计算逻辑不会出错。
方案2:强制按指定顺序反序列化
如果一定要用JsonProperty(Order),需要配合修改序列化设置的ObjectCreationHandling为Replace,这样序列化器会严格按Order顺序赋值:
修改类:
public class MyClass { private int secondVal; [JsonProperty(Order = 1)] public int FirstVal { get; set; } [JsonProperty(Order = 2)] public int SecondVal { get => secondVal + FirstVal; set => secondVal = value - FirstVal; } }
反序列化时设置:
var settings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace }; var myObj = JsonConvert.DeserializeObject<MyClass>(jsonString, settings);
方案3:通过临时存储+属性setter触发计算
给SecondVal的JSON值单独映射一个属性,根据FirstVal是否已赋值,决定立即计算还是临时存储:
public class MyClass { private int secondVal; private int? _pendingSecondVal; public int FirstVal { get => _firstVal; set { _firstVal = value; // 如果SecondVal的JSON值已经收到,立即计算 if (_pendingSecondVal.HasValue) { secondVal = _pendingSecondVal.Value - value; _pendingSecondVal = null; } } } private int _firstVal; // 专门接收JSON中的SecondVal [JsonProperty("SecondVal")] public int SecondValJson { set { if (_firstVal != default) { secondVal = value - _firstVal; } else { _pendingSecondVal = value; } } } // 对外暴露的计算后的值,不参与反序列化 [JsonIgnore] public int SecondVal => secondVal + FirstVal; }
内容的提问来源于stack exchange,提问作者Ashraf Gawdat
相关产品推荐
相关产品推荐

