更多内容见这里: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序列化器。

 

Json.Net学习笔记(十) 保持对象引用的更多相关文章

  1. python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例

    python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例 新浪爱彩双色球开奖数据URL:http://zst.aicai.com/ssq/openInfo/ 最终输出结果格 ...

  2. Json.Net学习笔记

    http://www.cnblogs.com/xiaojinhe2/archive/2011/10/28/2227789.html Newtonsoft.Json(Json.Net)学习笔记 http ...

  3. Learning ROS for Robotics Programming Second Edition学习笔记(十) indigo Gazebo rviz slam navigation

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 moveit是书的最后一章,由于对机械臂完全不知,看不懂 ...

  4. python3.4学习笔记(十八) pycharm 安装使用、注册码、显示行号和字体大小等常用设置

    python3.4学习笔记(十八) pycharm 安装使用.注册码.显示行号和字体大小等常用设置Download JetBrains Python IDE :: PyCharmhttp://www. ...

  5. python3.4学习笔记(十九) 同一台机器同时安装 python2.7 和 python3.4的解决方法

    python3.4学习笔记(十九) 同一台机器同时安装 python2.7 和 python3.4的解决方法 同一台机器同时安装 python2.7 和 python3.4不会冲突.安装在不同目录,然 ...

  6. python3.4学习笔记(十六) windows下面安装easy_install和pip教程

    python3.4学习笔记(十六) windows下面安装easy_install和pip教程 easy_install和pip都是用来下载安装Python一个公共资源库PyPI的相关资源包的 首先安 ...

  7. python3.4学习笔记(十五) 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)

    python3.4学习笔记(十五) 字符串操作(string替换.删除.截取.复制.连接.比较.查找.包含.大小写转换.分割等) python print 不换行(在后面加上,end=''),prin ...

  8. python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL

    python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL实战例子:使用pyspider匹配输出带.html结尾的URL:@config(a ...

  9. python3.4学习笔记(十) 常用操作符,条件分支和循环实例

    python3.4学习笔记(十) 常用操作符,条件分支和循环实例 #Pyhon常用操作符 c = d = 10 d /= 8 #3.x真正的除法 print(d) #1.25 c //= 8 #用两个 ...

随机推荐

  1. 万能的everything彻底解决mysql问题

    万能的everthing D:\RECYCLER\S-1-5-21-1214440339-1123561945-1801674531-500\Dd16.0\my.ini可能之前的电脑的隐藏文件没有删除 ...

  2. ios手势复习值之换图片-转场动画(纯代码)

    目标:实现通过手势进行图片的切换   通过左扫右扫 来实现(纯代码) 添加三个属性 1uiImageView 用来显示图片的view 2 index 用来表示图片的索引 3 ISLeft 判断是不是向 ...

  3. 段落排版--对齐(text-aliagn)

    想为块状元素中的文本.图片设置居中样式吗?可以使用text-align样式代码,如下代码可实现文本居中显示.(那么什么是块状元素呢?后面会讲到呢~) h1{ text-align:center; } ...

  4. Base64的用法

    如果要对一些图片进行保存,把他的文件名变成乱码,不让用户把他删掉,可以用Base64把他删掉用法如下: //获取访问图片的路径 String path=editText.getText().toStr ...

  5. H5相关

    对于容器元素,尤其在做移动端产品时候,我们很自然会让其居中定位: .container { position: absolute; left: %; top: %; transform: transl ...

  6. linux 定时执行shell

    第一步:安装 crontab ,命令 yum -y install vixie-cron                扩展:service crond start //启动服务            ...

  7. apache rewrite .htaccess 站点内容重定向实例

    <IfModule mod_rewrite.c> Options +FollowSymlinks RewriteEngine On RewriteCond %{REQUEST_FILENA ...

  8. openshif ssh proxy

    最近google又被墙了.没办法 1:注册一个openshift账号.申请注册一个app,获取一个免费主机.   https://www.openshift.com/ 2:去PuTTY官方网站下载pL ...

  9. To Build A Dev Env On Linux(Ubuntu)

    Step1:System Installing 1)use iso image to Step2:Configuration Step3:Software Installing Step4:Other ...

  10. react-redux原理

    react-redux原理分析 写在前面 之前写了一篇分析Redux中Store实现的文章(详见:Redux原理(一):Store实现分析),突然意识到,其实React与Redux并没有什么直接的联系 ...