zoukankan      html  css  js  c++  java
  • Newtonsoft.Json序列化踩坑:IEnumerable

       Newtonsoft.Json 是.net下广泛应用的JSON操作库,使用方便、数据可视化度高。但也总会踩坑……

      如果需要序列化的对象实现了IEnumerable接口,Newtonsoft.Json就会认为这个对象是一个数组,然后遍历这个对象,输出其中的值。如果这个对象还包含有其他的属性,那其他属性就会被忽略,序列化后发生数据丢失。

    测试源码:

    public class Test : IEnumerable
    {
        public string str1 = "字段字符串";
        public string str2 { get; set; } = "属性字符串";
    
        private string s="私有字段";
        public string S { get { return s; } set { s = value; } }
        [JsonProperty]
        List<TestNode> lstDrillTools = new List<TestNode>();
        public Test()
        {
            int index = 0;
            lstDrillTools.Add(new TestNode() { str1= (index++).ToString()});
            lstDrillTools.Add(new TestNode() { str1 = (index++).ToString() });
            lstDrillTools.Add(new TestNode() { str1 = (index++).ToString() });
            lstDrillTools.Add(new TestNode() { str1 = (index++).ToString() });
            lstDrillTools.Add(new TestNode() { str1 = (index++).ToString() });
        }
    
    
        [OnDeserializing()]
        internal void OnDeserializingMethod(StreamingContext context)
        {
            lstDrillTools.Clear();//反序列化前 清空
        }
    
        public TestNode this[int index]
        {
            get
            {
                return lstDrillTools[index];
            }
            set { lstDrillTools[index] = value; }
        }
    
        /// <summary>
        /// 遍历钻具组合
        /// </summary>
        /// <returns>返回钻具组合的枚举器</returns>
        public IEnumerator GetEnumerator()
        {
            if (lstDrillTools != null)
            {
                for (int i = 0; i < lstDrillTools.Count; i++)
                {
                    yield return lstDrillTools[i];
                }
            }
        }
    }
    
    public class TestNode
    {
        public string str1 = "字段字符串";
        public string str2 { get; set; } = "属性字符串";
    
        public bool isBool=false;
    }

      上面的这种定义相当于实现了 IEnumerable 接口,之所以实现这个接口,是因为可以直接遍历这个对象,不需要遍历这个对象的Data 属性上遍历。

      但使用了JsonConvert.SerializeObject()方法序列化对象后的结果如下图,它丢失了部分字段:

       实际想要的结果:

       如果想要这种结果,只需要不实现IEnumerable接口就可以做到。最开始,还是在查找原因,以及寻求解决方法。但直到看了Newtonsoft.Json 源码 https://github.com/JamesNK/Newtonsoft.Json ,找到为什么实现了 IEnumerable 接口就会有问题,最后找到了这里https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs#L1218 

      发现只要实现了 IEnumerable 接口,就会被当作是一个Json 数组,foreach 遍历其中的元素,其他属性就会被忽略掉了,这就是为什么上面我们实现了 IEnumerable 接口的对象序列化之后发生属性丢失的原因。

  • 相关阅读:
    asp.net 数据导出到Excel
    系统架构之畅想
    access2003绿色中文版(转)
    项目那点事(共享)
    不错的消息提示
    配置Windows media service 流媒体服务器
    MemberShip 数据库的安装,web.config的配置及数据库文档结构
    windows server 2003 service pack 2 无法安装...产品密钥可能无效
    残忍,人
    js小技巧鼠标滑过显示大图
  • 原文地址:https://www.cnblogs.com/pilgrim/p/13754015.html
Copyright © 2011-2022 走看看