zoukankan      html  css  js  c++  java
  • Json.Net学习笔记(十) 保持对象引用

    默认情况下,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; }
        }

    测试:

               List<EmployeeReference> empList = new List<EmployeeReference>();
                empList.Add(empRef);
                empList.Add(empRef);
                string empRefJson = JsonConvert.SerializeObject(empList, Formatting.Indented);
                Console.WriteLine(empRefJson);

    输出结果:

    [
      {
        "$id": "1",
        "Name": "IsReference",
        "Manager": null
      },
      {
        "$ref": "1"
      }
    ]

    >IReferenceResolver

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

  • 相关阅读:
    Leetcode 121. Best Time to Buy and Sell Stock
    Leetcode 120. Triangle
    Leetcode 26. Remove Duplicates from Sorted Array
    Leetcode 767. Reorganize String
    Leetcode 6. ZigZag Conversion
    KMP HDU 1686 Oulipo
    多重背包 HDU 2844 Coins
    Line belt 三分嵌套
    三分板子 zoj 3203
    二分板子 poj 3122 pie
  • 原文地址:https://www.cnblogs.com/aaa6818162/p/2251126.html
Copyright © 2011-2022 走看看