一尘不染

填充现有对象时,在添加项目之前清除集合

json

我有一个对象,该对象有几个用public
getter但私有setter定义的集合属性,在这种情况下,JsonConvert.PopulateObject将反序列化的项目添加到这些集合中,而现有的项目保持不变。

在反序列化之前清除此类成员集合时,我需要采取一种行为。

我尝试使用带有[OnDeserializing]属性的方法手动清除集合。

这种方法的问题在于,即使在JSON字符串中不存在collection属性,它仍将清除集合。

当仅清除那些在JSON字符串中实际定义的集合时,我需要一种方法。那些未定义的应该保持不变。

谢谢


阅读 179

收藏
2020-07-27

共1个答案

一尘不染

好的,因此,在访问Json.NET源代码后,我通过从继承了自定义合同解析器找到了以下解决方案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();
2020-07-27