2013-10-08 25 views
7

C# | .NET 4.5 | Entity Framework 5Buduj hierarchię JSON z danych strukturalnych

Mam dane wracające z zapytania SQL w postaci ID, ParentID, Name. Chciałbym wziąć te dane i przetworzyć je na hierarchiczny ciąg JSON. Jak dotąd wydaje się, że jest to zadanie bardziej zniechęcające niż powinno być. Ponieważ używam Entity, dane wracają ładnie do mnie jako IEnumerable. Teraz wierzę, że potrzebuję jakiejś formy rekurencji, ale nie jestem pewien, od czego zacząć. Każda pomoc jest doceniana.

danych Zwraca jako

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

Code jest

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

Końcowym rezultatem bym nadzieję byłoby coś takiego:

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

Odpowiedz

9

Jednym ze sposobów przekształcenia płaskiej tabeli w hierarchię jest umieszczenie wszystkich swoich węzłów w słowniku. Następnie wykonaj iterację w słowniku i dla każdego węzła wyszukaj jego rodzica i dodaj go do dzieci rodziców. Stamtąd wystarczy znaleźć root i serializować go.

Oto przykładowy program w celu wykazania podejście:

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

Oto wynik:

{ 
    "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

Jaki jest najlepszy sposób deserializacji? – Rod

+1

@Rod Aby deserializować musisz tylko zrobić 'Location loc = JsonConvert.DeserializeObject (json);' –

+0

Bardzo dziękuję:) – Rod

3

Próbowałem coś takiego w 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)));