2013-10-08 175 views
7

C# .NET 4.5 |實體框架5從結構化數據構建JSON層次結構

我有數據以ID,ParentID,Name的形式從SQL查詢返回。我想將這些數據解析爲Hierarchical JSON字符串。到目前爲止,這似乎是一個比應該更艱鉅的任務。由於我使用的是實體,所以數據可以很好地作爲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": [ 
       {} 
      ] 
     } 
    ] 
} 

回答

9

將平坦錶轉換爲層次結構的一種方法是將所有節點放入字典中。然後遍歷字典,併爲每個節點查找它的父節點並將其添加到父節點的子節點。從那裏,你只需要找到根目錄並將其序列化。

下面是一個例子程序來演示的辦法:

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": [] 
    } 
    ] 
} 
+0

什麼是反序列化它的最好方法? – Rod

+1

@Rod反序列化你只需要做'Location loc = JsonConvert.DeserializeObject (json);' –

+0

非常感謝:) – Rod

3

我想在JavaScript這樣的事情。

list = [ 
    { 
    id: 1, 
    title: 'home', 
    parent: null 
    }, 
    { 
    id: 2, 
    title: 'about', 
    parent: null 
    }, 
    { 
    id: 3, 
    title: 'team', 
    parent: 2 
    }, 
    { 
    id: 4, 
    title: 'company', 
    parent: 2 
    } 
] 

function treeify(list, idAttr, parentAttr, childrenAttr) { 
    if (!idAttr) idAttr = 'id'; 
    if (!parentAttr) parentAttr = 'parent'; 
    if (!childrenAttr) childrenAttr = 'children'; 
    var treeList = []; 
    var lookup = {}; 
    list.forEach(function(obj) { 
     lookup[obj[idAttr]] = obj; 
     obj[childrenAttr] = []; 
    }); 
    list.forEach(function(obj) { 
     if (obj[parentAttr] != null) { 
      lookup[obj[parentAttr]][childrenAttr].push(obj); 
     } else { 
      treeList.push(obj); 
     } 
    }); 
    return treeList; 
}; 

console.log(JSON.stringify(treeify(list)));