从结构化数据构建JSON层次结构

时间:2013-10-08 19:27:51

标签: c# json entity-framework json.net hierarchy

C#| .NET 4.5 |实体框架5

我以ID,ParentID,Name的形式从SQL查询返回数据。我想获取该数据并将其解析为Hierarchical JSON字符串。到目前为止,它似乎更应该是一项艰巨的任务。因为我正在使用Entity,所以数据作为IEnumerable很好地回馈给我。现在我相信我只需要某种形式的递归,但我不太清楚从哪里开始。任何帮助表示赞赏。

数据返回

id   parentId    name
1    1           TopLoc
2    1           Loc1
3    1           Loc2
4    2           Loc1A

代码

public static string GetJsonLocationHierarchy(long locationID)
{
    using (EntitiesSettings context = new EntitiesSettings())
    {
        // IEnumerable of ID,ParentID,Name
        context.GetLocationHierarchy(locationID);
    }
}

我希望最终的结果是这样的:

{
    "id": "1",
    "parentId": "1",
    "name": "TopLoc",
    "children": [
        {
            "id": "2",
            "parentId": "1",
            "name": "Loc1",
            "children": [
                {
                    "id": "4",
                    "parentId": "2",
                    "name": "Loc1A",
                    "children": [
                        {}
                    ]
                }
            ]
        },
        {
            "id": "3",
            "parentId": "1",
            "name": "Loc2",
            "children": [
                {}
            ]
        }
    ]
}

1 个答案:

答案 0 :(得分:12)

将平面表转换为层次结构的一种方法是将所有节点放入字典中。然后迭代字典,并为每个节点查找其父节点并将其添加到父节点的子节点。从那里,你只需要找到根并序列化它。

以下是演示该方法的示例程序:

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<Location> locations = new List<Location>
        {
            new Location { Id = 1, ParentId = 1, Name = "TopLoc" },
            new Location { Id = 2, ParentId = 1, Name = "Loc1" },
            new Location { Id = 3, ParentId = 1, Name = "Loc2" },
            new Location { Id = 4, ParentId = 2, Name = "Loc1A" },
        };

        Dictionary<int, Location> dict = locations.ToDictionary(loc => loc.Id);

        foreach (Location loc in dict.Values)
        {
            if (loc.ParentId != loc.Id)
            {
                Location parent = dict[loc.ParentId];
                parent.Children.Add(loc);
            }
        }

        Location root = dict.Values.First(loc => loc.ParentId == loc.Id);

        JsonSerializerSettings settings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            Formatting = Formatting.Indented
        };
        string json = JsonConvert.SerializeObject(root, settings);

        Console.WriteLine(json);
    }
}

class Location
{
    public Location()
    {
        Children = new List<Location>();
    }

    public int Id { get; set; }
    public int ParentId { get; set; }
    public string Name { get; set; }
    public List<Location> Children { get; set; }
}

这是输出:

{
  "id": 1,
  "parentId": 1,
  "name": "TopLoc",
  "children": [
    {
      "id": 2,
      "parentId": 1,
      "name": "Loc1",
      "children": [
        {
          "id": 4,
          "parentId": 2,
          "name": "Loc1A",
          "children": []
        }
      ]
    },
    {
      "id": 3,
      "parentId": 1,
      "name": "Loc2",
      "children": []
    }
  ]
}