Вопрос

I have result set that looks like this:

enter image description here

Which needs to be formatted into hierarchal json with nested groups:

     [
        {
            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 }
            ]
        }],

My initial thought was to group the data using a linq query:

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

But I am not clear on how to serialize this list once grouped. Also I am not confident in my grouping skills as I am a bit fuzzy on the sub select for iterating over each grouped rows (this code: .Select(group => new)...).

Other options I considered was using DataAnnotations/DataContracts and a custom annotation class, utilzing some advanced features of Newtonsoft JSON.NET, or using a dictionary and loading it up with the grouped rows.

I would be extremely grateful if someone can recommend the best practice for dealing with grouped data and JSON and help get me started on the code to output this grouped hierarchy (the sample JSON data I built by hand, but is the exact desired output).

I should mention for completeness sake, my end goal is to great a Kendo hierarchical data source javascript object: http://docs.kendoui.com/api/framework/hierarchicaldatasource

Это было полезно?

Решение

If you are only needing to display the data, you can always just get all of the records from your service, and do the grouping in javascript, then bind your hierarchical datasource to that.

Sample http://jsbin.com/uQuLUwE/2/edit (I just bound it to a treeview for easy display)

If not, you can always create two dataSources, one for the root items, and one for the childItems. The root items would need to pull the distinct AreaNames, and then the childItems datasource would need to be filtered for the proper AreaName.

Другие советы

Thank you for your suggestion - I ended up going with a probably over complicated c# method

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


}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top