Clear collections before adding items when populating existing objects

前端 未结 1 1245
孤城傲影
孤城傲影 2020-12-11 22:44

I have an object which has several collection properties defined with public getter but private setter, In this case JsonConvert.PopulateObject adds the deseria

相关标签:
1条回答
  • 2020-12-11 23:21

    Okay, so after some trip to Json.NET sources I found the following solution by inheriting a custom contract resolver from DefaultContractResolver.

    I needed to override the array contract creation to add a deserialization callback. At this point the callback receives the concrete collection instance, so we can manipulate it (in this case clear it).

    As long as I can determine, it is safe to use, but feel free to warn about any drawbacks of this method.

    Note: Am I the only one who feels that this should probably be the default behavior?

    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();
    
    0 讨论(0)
提交回复
热议问题