Парсинг JSON в TreeView
Находил схожий пример, но в нем рассматривается зависимость по id. У меня же стоит задача парсинга такого файла.
[
{
"Name":"Пикова Екатерина Львовна"
},
{
"Name":"1 отдел",
"Childs":[
{
"Name":"Петров Петр Петрович"
},
{
"Name":"1 кабинет",
"Childs":[
{
"Name":"Иванов Иван Иванович"
}
]
}
]
},
{
"Name":"2 отдел",
"Childs":[
{
"Name":"Антонов Антон Антонович"
},
{
"Name":"1 кабинет",
"Childs":[
{
"Name":"Егоров Егор Егорович"
}
]
},
{
"Name":"2 кабинет",
"Childs":[
{
"Name":"Сергеев Сергей Сергеевич"
}
]
},
{
"Name":"3 кабинет",
"Childs":[
{
"Name":"Алексеев Алексей Алексеевич"
}
]
}
]
},
{
"Name":"3 отдел",
"Childs":[
{
"Name":"Петухов Андрей Ринатович"
},
{
"Name":"1 кабинет",
"Childs":[
{
"Name":"Егоров Егор Егорович"
}
]
},
{
"Name":"4 кабинет",
"Childs":[
{
"Name":"Арахисов Игорь Сергеевич"
},
{
"Name":"Ульянов Владимир Ильич"
}
]
}
]
},
{
"Name":"4 отдел",
"Childs":[
{
"Name":"Сахаров Андрей Дмитриевич"
}
]
}
]
И попытка уложить его в TreeView, а после, что немаловажно, это укладка TreeView обратно в JSON.
Пробовал парсить его через класс:
public class Structure
{
public string Name { get; set; }
public string Childs { get; set; }
}
Но понял, что этот класс в корне неверен. Прошу помочь разобраться с этим.
UPD: За неимением лучшего варианта, было принято решение добавить в каждый узел хотя бы пустой объект "Childs": []
Теперь парсится это всё кодом:
var json = JToken.Parse(readText);
var structures = json.ToObject<Structure[]>();
for(int i = 0; i < structures.Length; i++)
{
person_tree.Nodes.Add(structures[i].Name);
if(structures[i].Childs.Length > 0)
{
for(int j = 0; j < structures[i].Childs.Length; j++)
{
person_tree.Nodes[i].Nodes.Add(structures[i].Childs[j].Name);
if(structures[i].Childs[j].Childs.Length > 0)
{
for (int q = 0; q < structures[i].Childs[j].Childs.Length; q++)
{
person_tree.Nodes[i].Nodes[j].Nodes.Add(structures[i].Childs[j].Childs[q].Name);
}
}
}
}
}
Но это действует только для глубины не более трех, а хочется рекурсию.
UPD2:
Для обратного парсинга, с учетом ответа KuzCode, пытаюсь написать
public Structure[] TreeNodeToStructure(TreeNode[] trees)
{
var structure = new List<Structure>();
foreach(var node in trees)
{
var str = new Structure();
str.Name = node.Name;
str.Childs = TreeNodeToStructure(node.Nodes);
structure.Add(str);
}
return structure.ToArray();
}
Но это явно делается не так
Ответы (1 шт):
Токен Childs в вашем json-е является самоподобным массивом, по-этому ему точно соответствует не тип string, а тип IEnumerable<Structure> или любой его наследник, массив, например.
Следует изменить класс Structure так:
public class Structure
{
public string Name { get; set; }
public Structure[] Childs { get; set; }
}
Тогда десериализация будет выглядеть так:
var jsonString = "ваш json";
var json = JToken.Parse(jsonString);
var structures = json.ToObject<Structure[]>();
UPD:
Чтобы превратить массив Structure в массив TreeNode необходимо использовать рекурсию:
public TreeNode[] StructuresToTreeNodes(Structure[] structures)
{
if (structures is null)
throw new ArgumentNullException(nameof(structures));
var nodes = new List<TreeNode>();
foreach (var structure in structures)
{
var node = new TreeNode(structure.Name);
if (structure.Childs != null && structure.Childs.Length > 0)
node.Nodes.AddRange(StructuresToTreeNodes(structure.Childs));
nodes.Add(node);
}
return nodes.ToArray();
}
Использовать так:
personTreeView.Nodes.AddRange(StructuresToTreeNodes(structures));
Результат:
UPD2:
public Structure[] TreeNodesToStructures(TreeNodeCollection nodes)
{
if (nodes is null)
throw new ArgumentNullException(nameof(nodes));
var structures = new List<Structure>();
foreach (TreeNode node in nodes)
{
var structure = new Structure() { Name = node.Text };
if (node.Nodes != null && node.Nodes.Count > 0)
structure.Childs = TreeNodesToStructures(node.Nodes);
structures.Add(structure);
}
return structures.ToArray();
}
