C#.NET:反序列化json树

时间:2015-10-18 18:56:47

标签: c# json tree json.net

晚上好,

对于我的具体问题,我必须创建一个菜单(更精确的菜单树)。因此,我决定使用具有以下结构的Composite Design Pattern:

  • IMenuComponent(定义某些属性的界面等)
  • 菜单(包含IMenuComponent列表)
  • MenuEntry(一片叶子)

因此,我必须在了解备份方式的同时浏览它。显而易见的答案是有一个父母'属性。

我有以下json树:

{
  "Guid": "08967257-9306-4717-a76a-e1a4f0050505",
  "Parent": null,
  "Title": "Main Menu",
  "Message": "A sample message",
  "Elements": [
    {
      "$type": "Menu",
      "Guid": "26dfca59-9163-4b11-8033-e8ad13f3f5cc",
      "Parent": "08967257-9306-4717-a76a-e1a4f0050505",
      "Title": "Option 1",
      "Message": "Another sample message",
      "Elements": [
        {
          "$type": "MenuEntry",
          "Parent": "26dfca59-9163-4b11-8033-e8ad13f3f5cc",
          "Title": "Entry 1",
          "Message": "Another sample message"
        },
        {
          "$type": "MenuEntry",
          "Parent": "26dfca59-9163-4b11-8033-e8ad13f3f5cc",
          "Title": "Entry 2",
          "Message": "Another sample message"
        },
        {
          "$type": "MenuEntry",
          "Parent": "26dfca59-9163-4b11-8033-e8ad13f3f5cc",
          "Title": "Entry 3",
          "Message": "Another sample message"
        }
      ]
    },
    {
      "$type": "MenuEntry",
      "Parent": "08967257-9306-4717-a76a-e1a4f0050505",
      "Title": "Option 2",
      "Message": "Another sample message"
    }
  ]
}

这不是关于反序列化本身,因为它的工作正常。

我的问题是,在将文件反序列化为“菜单”后,我必须访问父母。 (根)。 我可以想到两种方式:

  • 找到父母'在运行时使用它的Guid - 根据树的大小,性能可能很差;
  • 添加一个'菜单'两者的属性'菜单'和' MenuEntry'用于存储“父母”的课程。在从json反序列化之后,通过找到相应的Guid来填充它。基本上,我会在应用程序启动后立即将它放在一起,从而阻止在运行时查找。这也可能是表现不佳的。

要走的路是什么?我应该怎么做?

作为旁注,我使用Newtonsoft.Json

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

@Ian Mercer评论实际上帮我找到了一个简单的解决方案(使用上面帖子中描述的第二种方式)。

第二种方式并不真正依赖Guids。在反序列化之后,我可以迭代每个菜单集合(我可能会反正)并直接引用'parent'。

private void ConnectTree(Menu menu)
{
    foreach (IMenuComponent component in menu.Elements) {
        if (component is Menu) {
            (component as Menu).ParentMenu = menu;
            ConnectTree (component as Menu);
        } 
        else if (component is MenuEntry) {
            (component as MenuEntry).ParentMenu = menu;
        }
    }
}

只需拨打ConnectTree(_deserializedMenu)

即可

修改 @Brian Rogers刚从json net提到了PreserveReferencesHandling属性。最初的问题是关于json不支持循环引用,但这解决了它 - 它与使用Guids的逻辑相同。有多种解决方案,总是很有用。

谢谢!