我有一个对象,该对象有几个用public getter但私有setter定义的集合属性,在这种情况下,JsonConvert.PopulateObject将反序列化的项目添加到这些集合中,而现有的项目保持不变。
JsonConvert.PopulateObject
在反序列化之前清除此类成员集合时,我需要采取一种行为。
我尝试使用带有[OnDeserializing]属性的方法手动清除集合。
[OnDeserializing]
这种方法的问题在于,即使在JSON字符串中不存在collection属性,它仍将清除集合。
当仅清除那些在JSON字符串中实际定义的集合时,我需要一种方法。那些未定义的应该保持不变。
谢谢
好的,因此,在访问Json.NET源代码后,我通过从继承了自定义合同解析器找到了以下解决方案DefaultContractResolver。
DefaultContractResolver
我需要重写数组协定创建来添加反序列化回调。此时,回调接收到具体的集合实例,因此我们可以对其进行操作(在这种情况下,将其清除)。
只要我能确定,它就可以安全使用,但是请随时警告此方法的任何缺点。
注意:我是唯一认为这应该是默认行为的人吗?
public class CollectionClearingContractResolver : DefaultContractResolver { protected override JsonArrayContract CreateArrayContract(Type objectType) { var c = base.CreateArrayContract(objectType); c.OnDeserializingCallbacks.Add((obj, streamingContext) => { var list = obj as IList; if (list != null && !list.IsReadOnly) list.Clear(); }); return c; } } ... public class Test { public List<int> List { get; private set; } public Test() { List = new List<int>(); } } ... var myObj = new Test(); myObj.List.AddRange(new[] {1,2,3}); var listReference = myObj.List; JsonConvert.PopulateObject("{ List: [4, 5, 6] }", myObj, new JsonSerializerSettings { ContractResolver = new CollectionClearingContractResolver(), }); myObj.List.ShouldEqual(listReference); // didn't recreate list myObj.List.Count.ShouldEqual(3); myObj.List.SequenceEqual(new[] { 4, 5, 6}).ShouldBeTrue();