【问题标题】:Convert Hierarchical DataTable to Json将分层数据表转换为 Json
【发布时间】:2015-04-14 06:34:54
【问题描述】:

我有一个分层数据表,如下所示,它生成菜单及其子菜单。主菜单的 parentId 为 0。子菜单的父 ID 引用 parentId。

ResourceId   DisplayName   ParentId     Url
-----------------------------------------------
1           Home           0            Some Url
2           Student        0            Some Url
3           Staff          0            Some Url
4           Library        0            Some Url
6           StudentAtt     1            Some Url
7           TimeTable      1            Some Url
8           Staff Att      2            Some Url
9           Book Issue     3            Some Url
10          Book Return    3            Some Url
11          Fee Payment    4            Some Url
12          Book fine      10           Some Url

需要将其转换为 Json。下面是我试过的代码。我正在尝试检查 SubMenu 的 ParentId 是否等于主菜单的 ResourceId。但不显示子菜单。 (变量表为DataTable)

var rows = table.Rows.Cast<DataRow>().ToList();
            var result = rows.Where(x => x["ParentId"].ToString() == "0").GroupBy(r => new { x = r["ResourceId"] }).Select(
                g => new
                {
                    //MenuLevel = g.Key.x,
                    MenuDetails = g.GroupBy(r => new {a = r["DisplayName"], b = r["Url"]}).Select(
                        detail => new
                        {
                            DisplayName = detail.Key.a,
                            Url = detail.Key.b,
                            SubMenu =
                                detail.Where(y => g.Key.x.ToString()==y["ParentId"].ToString()).
                                    GroupBy(r => new {f = r["DisplayName"]}).Select(
                                    subMenu=>new
                                    {
                                        SubMenuDisplayName=subMenu.Key.f
                                    }
                                    )
                        }
                        )
                });

我得到的结果如下。

[{"MenuDetails":[{"DisplayName":"Home","Url":null,"SubMenu":[]}]},{"MenuDetails":[{"DisplayName":"Student","Url":null,"SubMenu":[]}]},{"MenuDetails":[{"DisplayName":"Staff","Url":null,"SubMenu":[]}]},{"MenuDetails":[{"DisplayName":"Library","Url":null,"SubMenu":[]}]}]

但预期的结果是:

[{"MenuDetails":[{"DisplayName":"Home","Url":null,"SubMenu":[{"SubMenuDisplayName":"StudentAtt"},{"SubMenuDisplayName":"TimeTable"}]}]},{"MenuDetails":[{"DisplayName":"Student","Url":null,"SubMenu":[{"SubMenuDisplayName":"Staff Att"}]}]},{"MenuDetails":[{"DisplayName":"Staff","Url":null,"SubMenu":[{"SubMenuDisplayName":"Book Issue"},{"SubMenuDisplayName":"Book Return"}]}]},{"MenuDetails":[{"DisplayName":"Library","Url":null,"SubMenu":[{"SubMenuDisplayName":"Fee Payment "}]}]}]

我还需要显示子子菜单(其父 id 指向子菜单的资源 id)任何人请帮助

【问题讨论】:

    标签: json linq datatable nested-lists sublist


    【解决方案1】:

    你遇到的问题

    SubMenu = detail.Where(y => ...
    

    ,详细信息已过滤到rows.Where(x =&gt; x["ParentId"].ToString() == "0"),因此不包括子项。

    这将更接近您想要的,但只返回前两个级别。

    var result = rows.Where(x => x["ParentId"].ToString() == "0").GroupBy(r => new { x = r["ResourceId"] }).Select(
        g => new {
            //MenuLevel = g.Key.x,
            MenuDetails = g.GroupBy(r => new { a = r["DisplayName"], b = r["Url"] }).Select(
                detail => new {
                    DisplayName = detail.Key.a,
                    Url = detail.Key.b,
                    SubMenu =
                        rows.Where(y => g.Key.x.ToString() == y["ParentId"].ToString()).
                            GroupBy(r => new { f = r["DisplayName"] }).Select(
                            subMenu => new {
                                SubMenuDisplayName = subMenu.Key.f
                            }
                            )
                }
                )
        });
    

    要创建完整的层次结构,您需要为每个菜单项创建对象,然后将它们连接在一起。如果您创建一个类型来表示您的菜单项,这会更容易,例如:

    public class MenuDeatils {
    
        public int ID;
        public string Url;
        public string DisplayName;
        public IEnumerable<MenuDeatils> SubMenu;
    
    }
    

    然后您可以为每个项目创建一个对象,并按它们的 ParentId 对它们进行分组:

    var groups = (from row in rows
                  group row by row["ParentId"] into parentGroup
                  select new {
                    Key = (int)parentGroup.Key,
                    Items = parentGroup.Select(r => new MenuDeatils {
                        ID = (int)r["ResourceId"],
                        DisplayName = (string)r["DisplayName"],
                        Url = (string)r["Url"]
                    })
                  }).ToList();
    

    注意:这里列举了查询 (.ToList()),因此我们创建了一组 MenuDetails 对象。

    接下来我们可以从我们创建的组中设置每个 MenuDetails 对象的 SubMenu 属性。

    foreach (var menuItem in groups.SelectMany(g => g.Items)) {
        var submenu = groups.SingleOrDefault(g => g.Key == menuItem.ID);
        if (submenu != null) {
            menuItem.SubMenu = submenu.Items;
        }
    };
    

    可以通过以下方式找到顶级项目:

    var result = groups.Single(g => g.Key == 0).Items
    

    ,现在已经附加了所有的子菜单。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-21
      • 2016-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-19
      相关资源
      最近更新 更多