简体   繁体   English

C#.net:反序列化json树

[英]C# .NET: Deserialize json tree

Good evening, 晚上好,

For my specific problem, I have to create a menu (a tree of menus more exactly). 对于我的特定问题,我必须创建一个菜单(更确切地说是菜单树)。 Thus, I decided to use Composite Design Pattern with the following structure: 因此,我决定使用具有以下结构的复合设计模式:

  • IMenuComponent (an interface defining some properties and so on) IMenuComponent(定义某些属性的接口,依此类推)
  • Menu (contains a list of IMenuComponent) 菜单(包含IMenuComponent的列表)
  • MenuEntry (a leaf) MenuEntry(一片叶子)

So, I'll have to navigate through it while knowing the way back up. 因此,我必须在了解备份方式的同时浏览它。 The obvious answer is having a 'parent' property. 显而易见的答案是拥有“父母”财产。

I have the following json tree: 我有以下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"
    }
  ]
}

This isn't about the deserialization itself, since that's working as it should. 这与反序列化本身无关,因为它可以正常工作。

My problem is that I'll have to access the parents after deserializing the file to a 'Menu' (the root). 我的问题是,在将文件反序列化为“菜单”(根)后,我将不得不访问父级。 I can think of two ways: 我可以想到两种方式:

  • Find a 'parent' in runtime using its Guid - can be bad performance-wise depending on tree size; 使用其Guid在运行时中找到“父级”-取决于树的大小,在性能方面可能会很差;
  • Add a 'Menu' property to both 'Menu' and 'MenuEntry' classes to store the 'parent' and fill it, by finding the corresponding Guid, after deserializing from json. 从json反序列化后,通过找到相应的Guid,将'Menu'属性添加到'Menu'和'MenuEntry'类中,以存储'parent'并填充它。 Basically, I'd put it together as soon as the application starts, preventing the find in runtime. 基本上,我会在应用程序启动后立即将它们放在一起,以防止在运行时查找。 It could be bad performance-wise as well. 在性能方面也可能是不好的。

What's the way to go? 怎么走? And how should I do it? 我该怎么办呢?

As a side note, I'm using Newtonsoft.Json 附带说明,我正在使用Newtonsoft.Json

Thanks for the help! 谢谢您的帮助!

@Ian Mercer comment actually helped me figure out a simple solution (using the 2nd way described in my post above). @Ian Mercer的评论实际上帮助我找到了一个简单的解决方案(使用上面我的帖子中描述的第二种方法)。

The 2nd way doesn't really rely on Guids. 第二种方法并不真正依赖Guid。 After the deserialize, I can just iterate over each menu collection (as I probably would anyway) and give the reference to the 'parent' directly. 反序列化之后,我可以遍历每个菜单集合(就像我可能无论如何都可以)并直接给“父级”提供引用。

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;
        }
    }
}

Just need to call ConnectTree(_deserializedMenu) 只需调用ConnectTree(_deserializedMenu)

Edit: @Brian Rogers just mentioned PreserveReferencesHandling property from json net. 编辑: @Brian Rogers刚刚提到了json net的PreserveReferencesHandling属性。 The original problem was all about json not supporting circular references, but that solves it - it's the same logic as using Guids. 最初的问题是关于json不支持循环引用,但这解决了它-与使用Guids的逻辑相同。 There are multiple solutions, which is always good to know. 有多种解决方案,这总是一个好消息。

Thanks! 谢谢!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM