Json.Net duplicates private list items

可紊 提交于 2019-12-11 11:39:08

问题


Currently I'm trying to utilize Json.Net serializer in my projects.

One of the problems that I've faced recentry is that deserialized object gets all of it's private list items duplicated. It can be reproduced like this:

  1. Create class with private field of List<> type, where List<> generic parameter is some other class
  2. Add public property, that gets/sets private field
  3. Create instance of that class, add 1 item to inner list, using property.
  4. Serialize with new DefaultContractResolver that is setup to see private class data;
  5. Deserialize

Code to reproduce the problem:

    public class ClassParam
    {
        public int? ParamOne
        {
            get;
            set;
        }
    }
    public class ClassWithParams
    {
        private List<ClassParam> _privateFieid = new List<ClassParam>();

        public List<ClassParam> PropertWithBackingField
        {
            get { return _privateFieid; }
            set { _privateFieid = value; }
        }

        public void AddElementToPrivateField(ClassParam classParam)
        {
            _privateFieid.Add(classParam);
        }

    }
    [Test]
    public void Test()
    {
            var instance = new ClassWithParams();

        var param1 = new ClassParam { ParamOne = 1 };

        instance.PropertWithBackingField.Add(param1);

        var contractResolver = new DefaultContractResolver();
        contractResolver.DefaultMembersSearchFlags |= BindingFlags.NonPublic;

        string serializedInstance = JsonConvert.SerializeObject(instance,
                                                                   Formatting.Indented,
                                                                   new JsonSerializerSettings()
                                                                   {
                                                                       ContractResolver = contractResolver

                                                                   });

        var deserializeInstance = JsonConvert.DeserializeObject(serializedInstance, typeof(ClassWithParams),
                                                                         new JsonSerializerSettings()
                                                                         {
                                                                             ContractResolver = contractResolver
                                                                         });
    }

When I remove public property PropertWithBackingField from ClassWithParams it's all ok. The problem is gone as well when I don't use custom setup for ContractResolver. But I do need to serialize private data of my classes as soon as not all of it is exposed via public properties.

What's wrong with my code? Are there any subtleties, using Json.Net or is it a bug?


回答1:


For this code

var s = JsonConvert.SerializeObject(instance);
var desInst = JsonConvert.DeserializeObject<ClassWithParams>(s);

Your json will be {"PropertWithBackingField":[{"ParamOne":1}]}

But you say to include private field in serialization/deserialization with

contractResolver.DefaultMembersSearchFlags |= BindingFlags.NonPublic;

and get a json

   {
  "_privateFieid": [
    {
      "ParamOne": 1
    }
  ],
  "PropertWithBackingField": [
    {
      "ParamOne": 1
    }
  ]
 }

So there are two deserializations, one for _privateFieid and one for PropertWithBackingField

Either use BindingFlags.Public or use my code above with is much simpler.




回答2:


DeserializeInstance method receives existing instance as argument. Probably it does not creates new instance but fills in existing and returns it.

Try to put ReferenceEquals(instance, deserializedInstance) to your watch. To avoid data duplicating use overload that does not accepts existing instance or create new instance and deserialize it.



来源:https://stackoverflow.com/questions/12615462/json-net-duplicates-private-list-items

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!