Convert Hierarchical DataTable to Json

瘦欲@ 提交于 2019-12-03 09:01:16

The issue your having is in

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

, detail is already filtered to rows.Where(x => x["ParentId"].ToString() == "0") so it does not include the child items.

This would be closer to what you want but only returns the first two levels.

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

To create the full hierarchy you need to create objects for each menu item then join them together. This is easier if you create a type to represent your menu item, for example:

public class MenuDeatils {

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

}

You can then create an object for each item and group them by their ParentIds:

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();

Note: The queries are enumerated here (.ToList()) so we create one set of MenuDeatils objects.

Next we can set each MenuDetails object's SubMenu property from the groups we have created.

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

The top level items can be found with:

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

, and now have all the descendant menus attached.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!