【问题标题】:Serialization pattern to maintain back-references维护反向引用的序列化模式
【发布时间】:2013-08-29 16:29:38
【问题描述】:

所以如果我两个对象之间是一对多的关系,我只能用一种方式序列化,否则在使用Json.NET时会出现循环错误。

我想以两种方式序列化对象,以便可以上下导航对象。

阅读 Json.NET 的文档后,我发现能够通过添加以属性名称为后缀的 shouldSerialize 方法来有条件地序列化 C# poco 属性。

参加经理和员工课程。一位经理有许多员工。我希望员工反向引用经理,但我只希望经理在经理不是员工的财产时引用员工。

{ 
  manager: {
   managerId: 1,
   attr1: 'blah',

   employees: [
    {
     employeeId:1,
     manager: {
      manager id: 1,
      attr1: 'blah',
      employees: **null**
     }
   ]
}

这可能吗?最好的方法是什么?

【问题讨论】:

    标签: c# json serialization json.net


    【解决方案1】:

    如果您以这种方式使用ShouldSerialize,那么您的反向引用将不会是反向引用。 Employee.Manager 将指向一个不同的 Manager,而不是在其Employees 属性中包含员工的那个。

    您应该改用JsonSerializerSettings.PreserveReferencesHandling,它专门设计用于使交叉链接成为可能并避免对象重复。

    class Program
    {
        private static void Main ()
        {
            var m = new Manager { Attr = "Attr1" };
            var e = new Employee { Attr = "Attr1", Manager = m };
            m.Employees = new[] { e };
            Console.WriteLine(JsonConvert.SerializeObject(m,
                new JsonSerializerSettings {
                    PreserveReferencesHandling = PreserveReferencesHandling.Objects,
                    Formatting = Formatting.Indented,
                }));
            Console.ReadKey();
        }
    }
    
    class Manager
    {
        public Employee[] Employees;
        public string Attr;
    }
    
    class Employee
    {
        public Manager Manager;
        public string Attr;
    }
    

    此代码将输出以下 JSON:

    {
      "$id": "1",
      "Employees": [
        {
          "$id": "2",
          "Manager": {
            "$ref": "1"
          },
          "Attr": "Attr1"
        }
      ],
      "Attr": "Attr1"
    }
    

    请注意,现在所有对象都具有$id 属性,并且当对象第二次出现在对象图中时,将插入对其的引用而不是对象:{ "$ref": "1" }

    【讨论】:

    • 因此,如果我的任务是确定员工的经理,我将遍历经理并将 $ref 属性与 $id 属性匹配。我几乎已经在这样做了,但是我更深入地研究了每个经理的所有员工,并确定经理是否包含我正在查看的员工。您建议的这种方式更加理智,并且考虑到 json 的限制,这似乎是最合理的解决方案。出于好奇,是否有任何序列化格式支持反向引用?
    • @Jesse XML 原生支持 id/idref,DataContractSerializer 支持此功能。 YAML 支持引用,但它们更像是复制粘贴而不是实际引用,而且它的库很糟糕。 JSON 本身不支持引用,但可以轻松扩展(就像在 JSON.NET 中所做的那样)。另请参阅维基百科页面:en.wikipedia.org/wiki/Comparison_of_data_serialization_formats(我不知道大多数格式,所以我无法评论它们。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-22
    • 1970-01-01
    • 1970-01-01
    • 2012-10-30
    • 2013-12-04
    • 1970-01-01
    相关资源
    最近更新 更多