更多内容见这里:http://www.cnblogs.com/wuyifu/archive/2013/09/03/3299784.html

默认情况下,Json.Net将通过对象的值来序列化它遇到的所有对象。如果工个list包含两个Person引用,这两个引用都指向同一个对象,Json序列化器将输出每一个引用的所有名称和值。

定义类:

public class Person
    {
        public DateTime BirthDate { get; set; }
        public DateTime LastModified { get; set; }
        public string Name { get; set; }
    }

测试:

Person p = new Person()
            {
                BirthDate = new DateTime(1985, 11, 27, 0, 0, 0, DateTimeKind.Utc),
                LastModified = new DateTime(2010, 12, 20, 0, 0, 0, DateTimeKind.Utc),
                Name = "James"
            };
            List<Person> people = new List<Person>();
            people.Add(p);
            people.Add(p);
            string json = JsonConvert.SerializeObject(people, Formatting.Indented);
            Console.WriteLine(json);

输出结果:

[
  {
    "BirthDate": "\/Date(501897600000)\/",
    "LastModified": "\/Date(1292803200000)\/",
    "Name": "James"
  },
  {
    "BirthDate": "\/Date(501897600000)\/",
    "LastModified": "\/Date(1292803200000)\/",
    "Name": "James"
  }
]

在大多数情况下这是期望的结果,但是在某些场景下,将list中的第二项作为第一项的一个引用来输出会是一个更好的解决方案。如果上面的Json现在被反序列化,返回的list会包含两个完全分离的对象,它们具有相同的值。通过值来输出引用也会在对象上导致循环引用的发生。

>PreserveReferencesHandling

string json2 = JsonConvert.SerializeObject(people, Formatting.Indented,
                new JsonSerializerSettings() { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
            Console.WriteLine(json2);

输出结果:

[
              {
                "$id": "1",
                "BirthDate": "\/Date(501897600000)\/",
                "LastModified": "\/Date(1292803200000)\/",
                "Name": "James"
              },
              {
                "$ref": "1"
              }
            ]

List<Person> deserializedPeople = JsonConvert.DeserializeObject<List<Person>>(json2,
                new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });

Console.WriteLine(deserializedPeople.Count);// 2

Person p1 = deserializedPeople[0];
            Person p2 = deserializedPeople[1];
            Console.WriteLine(p1.Name);// James
            Console.WriteLine(p2.Name);// James
            bool equal = Object.ReferenceEquals(p1, p2);// true

在list中的第一个Person被序列化时增加了一个额外的对象Id,现在第二个Person对象仅仅是第一个的引用。

现在使用PreserveReferencesHandling后,在序列化时只创建了一个Person对象,list中包含它的两个引用,原来我们叫作反射(mirroring) 。

>IsReference on JsonObjectAttribute, JsonArrayAttribute and JsonPropertyAttribute

在对象序列化器上设置PreserveReferencesHandling,将会改变所有对象被序列化和反序列化的方式。为了更加细致地控制对象和成员被序列化为一个引用,可以在JsonObjectAttribute, JsonArrayAttribute 和 JsonPropertyAttribute上使用IsReference 属性.

在JsonObjectAttribute, JsonArrayAttribute 上设置IsReference 为true,意味着Json序列化器总是会序列这个类型为一个引用。在JsonPropertyAttribute上设置IsReference为true将只序列化这个属性为一个引用。

[JsonObject(IsReference = true)]public class EmployeeReference{public string Name { get; set; }public EmployeeReference Manager { get; set; }}

测试:

static void Main(string[] args){List<EmployeeReference> empList = new List<EmployeeReference>();var empRef = new EmployeeReference{Name = "d1",Manager = new EmployeeReference{Name="d2",Manager  = new EmployeeReference{Name = "d3",Manager = null}}};empList.Add(empRef);empList.Add(empRef);string empRefJson = JsonConvert.SerializeObject(empList, Formatting.Indented);Console.WriteLine(empRefJson);Console.ReadLine();}

输出结果:

如果去掉 [JsonObject(IsReference = true)],那么输出如下:

>IReferenceResolver

要想定制引用的生成方式,可以继承自IReferenceResolver接口来使用Json序列化器。

转载于:https://www.cnblogs.com/niaowo/p/4744703.html

Json.Net学习笔记(十) 保持对象引用相关推荐

  1. Json.Net学习笔记(十二) 协议解析

    IContractResolver接口提供了一种方法去定制序列化器如何去序列化和反序列化.Net对象为Json对象 实现IContractResolver接口,然后为Json序列化器分配一个实例对象, ...

  2. Json.Net学习笔记

    Json.Net学习笔记 摘自:  http://www.verydemo.com/demo_c360_i45119.html 分类: 编程语言/ ASP.NET/ 文章 导读:string goog ...

  3. IOS之学习笔记十五(协议和委托的使用)

    1.协议和委托的使用 1).协议可以看下我的这篇博客 IOS之学习笔记十四(协议的定义和实现) https://blog.csdn.net/u011068702/article/details/809 ...

  4. 吴恩达《机器学习》学习笔记十四——应用机器学习的建议实现一个机器学习模型的改进

    吴恩达<机器学习>学习笔记十四--应用机器学习的建议实现一个机器学习模型的改进 一.任务介绍 二.代码实现 1.准备数据 2.代价函数 3.梯度计算 4.带有正则化的代价函数和梯度计算 5 ...

  5. 吴恩达《机器学习》学习笔记十二——机器学习系统

    吴恩达<机器学习>学习笔记十二--机器学习系统 一.设计机器学习系统的思想 1.快速实现+绘制学习曲线--寻找重点优化的方向 2.误差分析 3.数值估计 二.偏斜类问题(类别不均衡) 三. ...

  6. 吴恩达《机器学习》学习笔记十——神经网络相关(2)

    吴恩达<机器学习>学习笔记十--神经网络相关(2) 一. 代价函数 二. 反向传播算法 三. 理解反向传播算法 四. 梯度检测 五. 随机初始化 1.全部初始化为0的问题 2.随机初始化的 ...

  7. Mr.J-- jQuery学习笔记(十九)--自定义动画实现图标特效

    之前有写过自定义动画Mr.J-- jQuery学习笔记(十八)--自定义动画 这次实现一个小demo 图标特效 页面渲染 <!DOCTYPE html> <html lang=&qu ...

  8. Mr.J-- jQuery学习笔记(十六)--展开和收起动画折叠菜单的实现

    之前写过动画的隐藏与显示:Mr.J-- jQuery学习笔记(十四)--动画显示隐藏 动画隐藏与显示的一个小demo--对联广告:Mr.J-- jQuery学习笔记(十五)--实现页面的对联广告 与动 ...

  9. Mr.J-- jQuery学习笔记(十五)--实现页面的对联广告

    请看之前的:Mr.J-- jQuery学习笔记(十四)--动画显示隐藏 话不多说,直接上demo <!DOCTYPE html> <html lang="en"& ...

最新文章

  1. 视觉进阶 | 用于图像降噪的卷积自编码器
  2. 新年到了,该规划一下来年了
  3. php如何设定隐藏四位号码,PHP问题:php手机号码中间四位如何隐藏?
  4. 网管必备的十大网络安全测试工具
  5. Oracle之SQL分析函数
  6. 基于eclipse swt做java浏览器内嵌等功能
  7. linux安装程序过程,linux 应用程序安装过程
  8. 常用方法 保证数据长度相同
  9. ireport5.6+jasperreport6.3开发(四)--以javabean为基准的报表开发(ireport)
  10. 和情商高的人聊天是什么样的体验?
  11. vue页面乱码_项目部署到weblogic后页面乱码问题
  12. C语言二维数组范德蒙,2、编写一个程序,实现一个3×4矩阵转置。
  13. 秒解UTF-8带来的烦恼
  14. 银河麒麟专用服务器RPM软件包打包方式。
  15. 【论文阅读】DCAN: Deep Contour-Aware Networks for Accurate Gland Segmentation
  16. halocn标定找旋转中心_halcon应用案例探究
  17. Jqurey学习(1)
  18. 如何为QT窗体添加工具栏和菜单栏
  19. ajax零基础整个gitt核心内容全套
  20. vue-directive 自定义指令实现popover气泡弹窗

热门文章

  1. linux命令mount是什么,Linux命令——mount、umount
  2. jar包在linux定时调度,xshell脚本启动JAR包-定时任务拆分日志
  3. Python-Matplotlib可视化(5)——添加自定义形状绘制复杂图形
  4. phpcount数组报错_joomla中的PHP错误警告:count():参数必须是实现Countable的数组或对象-问答-阿里云开发者社区-阿里云...
  5. 不用sqrt实现平方根_如何在R中使用sqrt()查找平方根?
  6. python斐波那契递归_Python递归斐波那契示例
  7. Java中的会话管理– HttpServlet,Cookie,URL重写
  8. c语言静态函数调用静态变量_C语言中的静态变量和函数
  9. dagger2 注入_Android依赖注入– Dagger 2
  10. Advanced Installer 历史版本下载