Парсинг 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 шт):

Автор решения: KuzCode

Токен 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();
}
→ Ссылка