【问题标题】:Serialize object using JSON.net when json object has $ref to root object list当 json 对象具有 $ref 到根对象列表时,使用 JSON.net 序列化对象
【发布时间】:2017-01-25 08:19:25
【问题描述】:

我想知道当内部对象引用根对象列表的项目时是否可以序列化对象。小例子来说明:情况:

class Project
{
    public List<Template> Templates { get; set; }
    public List<Task> Tasks { get; set; }
}

class Template
{
    public string Name { get; set; }
}

class Task
{        
    public Template Template { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var template2 = new Template { Name = "Temp2" };

        var project = new Project
        {
            Templates = new List<Template>
            {
                new Template {Name = "Temp1"},
                template2,
                new Template {Name = "Temp3"}
            }
        };

        var task = new Task {Template = template2};

        project.Tasks = new List<Task> {task};

        Console.WriteLine(ReferenceEquals(project.Templates[1], project.Tasks.First().Template));

        var json = JsonConvert.SerializeObject(project);

        var projectFromJson =
            JsonConvert.DeserializeObject<Project>(
                "{\"Templates\":[{\"Name\":\"Temp1\"},{\"Name\":\"Temp2\"},{\"Name\":\"Temp3\"}],\"Tasks\":[{\"Template\":{\"$ref\":\"$.Templates[?@.Name == 'Temp2']\"}}]}");

        Console.WriteLine(ReferenceEquals(projectFromJson.Templates[1], projectFromJson.Tasks.First().Template));

        Console.Read();
    }
}

所以在本例中,我希望具有属性 Template 的 Task 对象将引用 Project 对象模板列表中的 template2 对象。所以在序列化ReferenceEquals之前创建它显示两个对象引用是相等的,但是当反序列化后再次尝试时它返回false,因为Task对象模板属性为null,这意味着JSON.net不要序列化它。

现在看起来同一个 JSON.net JObject 知道 JSONpath 语法,但它不适用于反序列化。我知道有 IReferenceResolver,但我不确定这个对我的情况有何帮助。

那么是否可以使用 JSON.net,也许还有其他序列化程序允许拥有 JSONpath 引用?

【问题讨论】:

    标签: c# json serialization json.net


    【解决方案1】:

    这就是PreserveReferencesHandling 的用途:

    // ...
    var settings = new JsonSerializerSettings { 
        PreserveReferencesHandling = PreserveReferencesHandling.Objects
    };
    var json = JsonConvert.SerializeObject(project, settings);
    var projectFromJson = JsonConvert.DeserializeObject<Project>(json);
    Console.WriteLine(ReferenceEquals(projectFromJson.Templates[1],
        projectFromJson.Tasks.First().Template));
    
    // This outputs "True"
    

    请注意,Json.NET 使用自己的引用语法而不是 JSONpath。对象层次结构的 JSON 如下所示:

    {
      "$id": "1",
      "Templates": [
        {
          "$id": "2",
          "Name": "Temp1"
        },
        {
          "$id": "3",
          "Name": "Temp2"
        },
        {
          "$id": "4",
          "Name": "Temp3"
        }
      ],
      "Tasks": [
        {
          "$id": "5",
          "Template": {
            "$ref": "3"
          }
        }
      ]
    }
    

    【讨论】:

    • 嗨,德米特里,它就像魅力一样,谢谢!需要注意的一件事是,如果我在任务列表之后有模板列表,则对象的顺序很重要,它没有找到该引用。
    • @Evaldas,不客气!我相信对象顺序应该无关紧要。我在任务之后尝试了模板,并使用以下 JSON 获得了相同的“真”:{ "$id": "1", "Tasks": [ { "$id": "2", "Template": { "$id": "3", "Name": "Temp2" } } ], "Templates": [ { "$id": "4", "Name": "Temp1" }, { "$ref": "3" }, { "$id": "5", "Name": "Temp3" } ] }
    • 我有 $ref 序列化问题,这些对我有帮助 stackoverflow.com/a/64910995/1831734
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-24
    • 1970-01-01
    • 1970-01-01
    • 2011-05-30
    • 2016-10-01
    相关资源
    最近更新 更多