Json.Net复制私有列表项

时间:2012-09-27 06:35:45

标签: c# json.net

目前我正在尝试在我的项目中使用Json.Net序列化程序。

我遇到的一个问题是,反序列化的对象会获取所有重复的私有列表项。 它可以像这样再现:

  1. 使用private类型的List<>字段创建类,其中List<>泛型参数是其他类
  2. 添加public属性,获取/设置private字段
  3. 创建该类的实例,使用属性将1项添加到内部列表。
  4. 使用设置为查看私有类数据的新DefaultContractResolver进行序列化;
  5. 反序列化
  6. 重现问题的代码:

        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
                                                                             });
        }
    

    1 http://s019.radikal.ru/i619/1209/7a/e342f5f5b97e.png

    当我从PropertWithBackingField删除公共财产ClassWithParams时,一切正常。 当我不使用ContractResolver的自定义设置时,问题也消失了。但是,一旦并非所有类的私有数据都通过公共属性公开,我确实需要序列化我的类的私有数据。

    我的代码出了什么问题?使用Json.Net是否有任何细微之处,还是一个bug?

2 个答案:

答案 0 :(得分:1)

对于此代码

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

你的json将是{"PropertWithBackingField":[{"ParamOne":1}]}

但是你说要用

包含序列化/反序列化中的私有字段
contractResolver.DefaultMembersSearchFlags |= BindingFlags.NonPublic;

并获得一个json

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

因此,有两个反序列化,一个用于_privateFieid,另一个用于PropertWithBackingField

使用BindingFlags.Public或使用上面的代码更简单。

答案 1 :(得分:-2)

DeserializeInstance方法接收现有实例作为参数。可能它不会创建新实例但会填充现有实例并将其返回。

尝试将ReferenceEquals(instance, deserializedInstance)放到手表上。为避免数据重复,请使用不接受现有实例的重载或创建新实例并对其进行反序列化。