• Json.Net学习笔记(十) 保持对象引用


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

     
  • 相关阅读:
    微信表情代码
    SQL四个排名函数(row_number、rank、dense_rank和ntile)的使用
    JS获取URL传过来的参数
    QQ在线咨询代码
    AJAX定时请求数据
    C#模拟登录主动推送信息
    HTML 5实现手机摇一摇的功能
    禁用站点asp运行
    二维码扫描极速版4.0.apk
    .NET Framework4网站 无法运行,提示找不到网络名,IO错误等解决办法
  • 原文地址:https://www.cnblogs.com/niaowo/p/4744703.html
Copyright © 2020-2023  润新知