Json.Net复制私人列表项 [英] Json.Net duplicates private list items

查看:59
本文介绍了Json.Net复制私人列表项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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. 使用List<>类型的private字段创建类,其中List<>通用参数是其他一些类
  2. 添加public属性,该属性获取/设置private字段
  3. 创建该类的实例,使用属性将1项添加到内部列表中.
  4. 使用新的DefaultContractResolver序列化,该DefaultContractResolver设置为查看私有类数据;
  5. 反序列化
  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

重现该问题的代码:

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

当我从ClassWithParams中删除公共财产PropertWithBackingField时,一切正常. 当我不对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.

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

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

推荐答案

此代码

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

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

但是您说要在序列化/反序列化中包含私有字段

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

contractResolver.DefaultMembersSearchFlags |= BindingFlags.NonPublic;

并获取一个json

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

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

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

使用BindingFlags.Public或使用我上面的代码都简单得多.

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

这篇关于Json.Net复制私人列表项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆