【问题标题】:Grouping a flat list and output hierarchical JSON对平面列表进行分组并输出分层 JSON
【发布时间】:2014-01-17 22:57:20
【问题描述】:

我的结果集如下所示:

需要用嵌套组格式化成层次结构的json:

     [
        {
            areaName: "Latam",
            subsidaries: [
                { areaName: "Ecuador", id: 1 },
                { areaName: "Peru", id: 3 },
                { areaName: "Jamaica", id: 4 },
                { areaName: "Venezuela", id: 5 },
                { areaName: "BCBB", id: 6 }
            ]
        },
        {
            areaName: "APAC",
            subsidaries: [
                { areaName: "Brunei", id: 1 },
                { areaName: "Sri Lanka", id: 31 },
                { areaName: "(APAC Sub Not Specified)", id: 1 },
                { areaName: "Korea", id: 231 },
                { areaName: "Malaysia", id: 61 },
                { areaName: "Indonesia", id: 61 },
                { areaName: "Philippines", id: 31 },
                { areaName: "Singapore", id: 3231 },
                { areaName: "Australia", id: 621 },
                { areaName: "New Zealand", id: 231 },
                { areaName: "Vietnam", id: 431 },
                { areaName: "Thailand", id: 99 }
            ]
        }],

我最初的想法是使用 linq 查询对数据进行分组:

    public ActionResult Index()
    {
        var model = Repository.GetGeoSubsidiaryHierarchy();

        foreach (var line in GroupedItems(model)
           .Select(group => new
           {
               AreaName = group.Key,
               Count = group.Count()
           }).OrderBy(x => x.AreaName))
        {
            Response.Write( String.Format( "{0} {1}", line.AreaName, line.Count) );
        }

        return View("Index", model);
    }

    private static IEnumerable<IGrouping<string, GeoSubsidiary>> GroupedItems(List<GeoSubsidiary> model)
    {
        var ret = model.ToList().GroupBy(area => area.AreaName);


        return ret;
    }

但我不清楚如何在分组后序列化此列表。此外,我对自己的分组技巧没有信心,因为我对迭代每个分组行的子选择有点模糊(此代码:.Select(group => new)...)。

我考虑的其他选项是使用 DataAnnotations/DataContracts 和自定义注释类,利用 Newtonsoft JSON.NET 的一些高级功能,或者使用字典并将其与分组的行一起加载。

如果有人能推荐处理分组数据和 JSON 的最佳实践并帮助我开始编写代码以输出此分组层次结构(我手工构建的示例 JSON 数据,但正是我想要的),我将不胜感激输出)。

为了完整起见,我应该提一下,我的最终目标是创建一个出色的 Kendo 分层数据源 javascript 对象:http://docs.kendoui.com/api/framework/hierarchicaldatasource

【问题讨论】:

  • 您需要完整的 CRUD 还是只显示?

标签: json linq kendo-ui kendo-treeview


【解决方案1】:

如果您只需要显示数据,您总是可以从您的服务中获取所有记录,并在 javascript 中进行分组,然后将您的分层数据源绑定到该数据源。

示例http://jsbin.com/uQuLUwE/2/edit(我只是将它绑定到树视图以便显示)

如果没有,您始终可以创建两个数据源,一个用于根项,一个用于子项。根项需要提取不同的 AreaNames,然后需要过滤 childItems 数据源以获得正确的 AreaName。

【讨论】:

    【解决方案2】:

    感谢您的建议 - 我最终选择了一个可能过于复杂的 c# 方法

    public class HierarchalDataController : BaseController
    {
    
        internal class ChildNode
        {
            public string areaName { get; set; }
            public int id { get; set; }
        }
    
        internal class Area
        {
            public string areaName { get; set; }
            public List<ChildNode> subsidaries { get; set; }
        }
    
        public ContentResult GetAreaContent()
        {
            var areas = Repository.GetGeoSubsidiaryHierarchy();
            var groupedAreas = areas.GroupBy(area => area.AreaName);
            var subareas = new List<Area>();
    
            foreach (var parentArea in groupedAreas)
            {
                var subsidiaries = new List<ChildNode>();
                var subs = areas.Where(x => x.AreaName == parentArea.Key).ToList();
                subsidiaries.AddRange(subs.Select(sub => new ChildNode { id = sub.SubsidiaryId, areaName = sub.SubsidiaryName }));
                var area = new Area { areaName = parentArea.Key, subsidaries = subsidiaries };
                subareas.Add(area);
            }
    
            var retval = JsonConvert.SerializeObject(subareas, Formatting.Indented);
            return Content(retval, "application/json");
        }
    
        public ContentResult GetScenarioContent()
        {
            var areas = Repository.GetScenarioHierarchy();
            var groupedAreas = areas.GroupBy(area => area.FunctionalAreaID);
            var subareas = new List<Area>();
    
            foreach (IGrouping<int, Scenario> parentArea in groupedAreas)
            {
                var subsidiaries = new List<ChildNode>();
                var subs = areas.Where(x => x.FunctionalAreaID== parentArea.Key).ToList();
                subsidiaries.AddRange(subs.Select(sub => new ChildNode { id = sub.FunctionalAreaID, areaName = sub.ScenarioName}));
                var scenario = parentArea.FirstOrDefault();
    
                if (scenario != null)
                {
                    var area = new Area { areaName = scenario.FunctionalAreaName, subsidaries = subsidiaries }; // hack
                    subareas.Add(area);
                }
            }
    
            var retval = JsonConvert.SerializeObject(subareas, Formatting.Indented);
            return Content(retval, "application/json");
        }
    
        /// <summary>
        /// Simply a flat-list of products. 
        /// </summary>
        /// <returns></returns>
        public ContentResult GetProductContent()
        {
            var subareas = new List<Area>();
            foreach (var product in Repository.GetProductList())
            {
                subareas.Add(new Area
                {
                    areaName = product.ProductName,
                    subsidaries = new List<ChildNode>()
                });
            }
    
            var retval = JsonConvert.SerializeObject(subareas, Formatting.Indented);
            return Content(retval, "application/json");
        }
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-18
      • 1970-01-01
      • 2015-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多