[C#][Newtonsoft.Json] Как привести многоуровневый JSON к одноуровнему с сохранением информации в список?

djaga

Administrator
Команда форума
Регистрация
26.04.2020
Сообщения
546
Благодарностей
1 125
Баллы
93
Привет. Подскажите, пожалуйста, как реализовать приведение многоуровневого JSON к одноуровнему с сохранением информации в список?
У меня есть тестовый проект, получил от него вот такой JSON
Категории:
[
  {
    "id": 3,
    "title": "Шины и диски",
    "link": "/catalogs2/3",
    "children": [
      {
        "id": 201,
        "title": "Шины",
        "link": "/catalogs2/201"
      },
      {
        "id": 202,
        "title": "Диски",
        "link": "/catalogs2/202"
      },
      {
        "id": 86,
        "title": "Камеры",
        "link": "/catalogs2/wheelcamera"
      }
    ]
  },
  {
    "id": 4,
    "title": "Масла и автохимия",
    "link": "/catalogs2/4",
    "children": [
      {
        "id": 41,
        "title": "Масла",
        "link": "/catalogs2/41",
        "children": [
          {
            "id": 211,
            "title": "гидравлические",
            "link": "/catalogs2/211"
          },
          {
            "id": 212,
            "title": "моторные",
            "link": "/catalogs2/212"
          },
          {
            "id": 213,
            "title": "индустриальные редукторные",
            "link": "/catalogs2/213"
          },
          {
            "id": 214,
            "title": "промывочные",
            "link": "/catalogs2/214"
          },
          {
            "id": 215,
            "title": "трансмиссионные",
            "link": "/catalogs2/215"
          },
          {
            "id": 75,
            "title": "амортизационные",
            "link": "/catalogs2/fluids-amortization"
          }
        ]
      },
      {
        "id": 42,
        "title": "Жидкости",
        "link": "/catalogs2/42",
        "children": [
          {
            "id": 216,
            "title": "AdBlue",
            "link": "/catalogs2/216"
          },
          {
            "id": 217,
            "title": "охлаждающие",
            "link": "/catalogs2/217"
          },
          {
            "id": 218,
            "title": "стеклоомывателя",
            "link": "/catalogs2/218"
          },
          {
            "id": 219,
            "title": "тормозные",
            "link": "/catalogs2/219"
          }
        ]
      },
      {
        "id": 43,
        "title": "Присадки",
        "link": "/catalogs2/43",
        "children": [
          {
            "id": 220,
            "title": "в масла",
            "link": "/catalogs2/220"
          },
          {
            "id": 221,
            "title": "в систему охлаждения",
            "link": "/catalogs2/221"
          },
          {
            "id": 222,
            "title": "топливные",
            "link": "/catalogs2/222"
          }
        ]
      },
      {
        "id": 255,
        "title": "Смазки",
        "link": "/catalogs2/255"
      },
      {
        "id": 281,
        "title": "Уход и очистка",
        "link": "/catalogs2/281"
      },
      {
        "id": 24,
        "title": "Автокосметика",
        "link": "/catalogs2/cosmetic"
      },
      {
        "id": 26,
        "title": "Остальное",
        "link": "/catalogs2/chemistry"
      }
    ]
  },
  {
    "id": 5,
    "title": "Электрооборудование",
    "link": "/catalogs2/5",
    "children": [
      {
        "id": 231,
        "title": "Аккумуляторы",
        "link": "/catalogs2/231"
      },
      {
        "id": 232,
        "title": "Батарейки",
        "link": "/catalogs2/232"
      },
      {
        "id": 233,
        "title": "Лампы",
        "link": "/catalogs2/233"
      },
      {
        "id": 246,
        "title": "Мойки высокого давления",
        "link": "/catalogs2/246"
      },
      {
        "id": 249,
        "title": "Подметальные машины",
        "link": "/catalogs2/249"
      },
      {
        "id": 269,
        "title": "Провода пусковые",
        "link": "/catalogs2/269"
      },
      {
        "id": 263,
        "title": "Пылесосы",
        "link": "/catalogs2/263"
      },
      {
        "id": 250,
        "title": "Устройства пуско-зарядные",
        "link": "/catalogs2/250"
      },
      {
        "id": 38,
        "title": "Компрессоры, насосы и манометры",
        "link": "/catalogs2/electro-compressors"
      },
      {
        "id": 52,
        "title": "Видеорегистраторы",
        "link": "/catalogs2/electro-dvrs"
      },
      {
        "id": 47,
        "title": "Автозвук",
        "link": "/catalogs2/electro-sound"
      },
      {
        "id": 55,
        "title": "Парковочные радары и камеры",
        "link": "/catalogs2/electro-parktronic"
      },
      {
        "id": 54,
        "title": "Противоугонные устройства",
        "link": "/catalogs2/electro-alarms"
      },
      {
        "id": 44,
        "title": "Подогреватели двигателя",
        "link": "/catalogs2/electro-engineheater"
      },
      {
        "id": 56,
        "title": "Радар-детекторы",
        "link": "/catalogs2/electro-detectors"
      },
      {
        "id": 41,
        "title": "Остальное",
        "link": "/catalogs2/electro-autoelectronics"
      }
    ]
  },
  {
    "id": 6,
    "title": "Инструменты",
    "link": "/catalogs2/6",
    "children": [
      {
        "id": 252,
        "title": "Головки торцевые",
        "link": "/catalogs2/252"
      },
      {
        "id": 241,
        "title": "Домкраты",
        "link": "/catalogs2/241"
      },
      {
        "id": 243,
        "title": "Ключи баллонные",
        "link": "/catalogs2/243"
      },
      {
        "id": 247,
        "title": "Наборы инструментов",
        "link": "/catalogs2/247"
      },
      {
        "id": 248,
        "title": "Отвёртки",
        "link": "/catalogs2/248"
      },
      {
        "id": 256,
        "title": "Хомуты",
        "link": "/catalogs2/256"
      },
      {
        "id": 70,
        "title": "Ручной инструмент",
        "link": "/catalogs2/tools-hand"
      },
      {
        "id": 38,
        "title": "Компрессоры, насосы и манометры",
        "link": "/catalogs2/electro-compressors"
      },
      {
        "id": 72,
        "title": "Электроинструмент",
        "link": "/catalogs2/tools-power"
      },
      {
        "id": 74,
        "title": "Пневмоинструмент",
        "link": "/catalogs2/tools-pneumatic"
      },
      {
        "id": 67,
        "title": "Измерительный инстр.",
        "link": "/catalogs2/tools-measuring"
      },
      {
        "id": 71,
        "title": "Хранение инструмента",
        "link": "/catalogs2/tools-storage"
      }
    ]
  },
  {
    "id": 7,
    "title": "Интерьер",
    "link": "/catalogs2/7",
    "children": [
      {
        "id": 224,
        "title": "Ароматизаторы",
        "link": "/catalogs2/224"
      },
      {
        "id": 263,
        "title": "Пылесосы",
        "link": "/catalogs2/263"
      },
      {
        "id": 266,
        "title": "Накидки с обогревом",
        "link": "/catalogs2/266"
      },
      {
        "id": 267,
        "title": "Оплётки на руль",
        "link": "/catalogs2/267"
      },
      {
        "id": 32,
        "title": "Коврики",
        "link": "/catalogs2/other-carpets"
      },
      {
        "id": 33,
        "title": "Чехлы и накидки",
        "link": "/catalogs2/other-covers"
      },
      {
        "id": 43,
        "title": "Автокресла",
        "link": "/catalogs2/other-seat"
      },
      {
        "id": 42,
        "title": "Держатели и столики",
        "link": "/catalogs2/other-holders"
      }
    ]
  },
  {
    "id": 8,
    "title": "Экстерьер",
    "link": "/catalogs2/8",
    "children": [
      {
        "id": 60,
        "title": "Дефлекторы",
        "link": "/catalogs2/other-deflectors"
      },
      {
        "id": 29,
        "title": "Защита на автомобиль",
        "link": "/catalogs2/other-protection"
      },
      {
        "id": 30,
        "title": "Фаркопы",
        "link": "/catalogs2/other-towbar"
      },
      {
        "id": 59,
        "title": "Багажные системы",
        "link": "/catalogs2/other-baggage"
      },
      {
        "id": 28,
        "title": "Внешний декор",
        "link": "/catalogs2/decor"
      },
      {
        "id": 272,
        "title": "Щётки стеклоочистителя",
        "link": "/catalogs2/272"
      }
    ]
  },
  {
    "id": 9,
    "title": "Остальное",
    "link": "/catalogs2/9",
    "children": [
      {
        "id": 262,
        "title": "Автоодеяла",
        "link": "/catalogs2/262"
      },
      {
        "id": 90,
        "title": "Защита и гигиена",
        "link": "/catalogs2/medicine",
        "children": []
      },
      {
        "id": 264,
        "title": "Велосипеды",
        "link": "/catalogs2/264"
      },
      {
        "id": 251,
        "title": "Герметики",
        "link": "/catalogs2/251"
      },
      {
        "id": 265,
        "title": "Жилеты светоотражающие сигнальные",
        "link": "/catalogs2/265"
      },
      {
        "id": 253,
        "title": "Клеи",
        "link": "/catalogs2/253"
      },
      {
        "id": 242,
        "title": "Канистры",
        "link": "/catalogs2/242"
      },
      {
        "id": 268,
        "title": "Очистка от снега, льда и воды",
        "link": "/catalogs2/268"
      },
      {
        "id": 254,
        "title": "Ремни поликлиновые",
        "link": "/catalogs2/254"
      },
      {
        "id": 271,
        "title": "Светофильтры",
        "link": "/catalogs2/271"
      },
      {
        "id": 65,
        "title": "Для автосервиса",
        "link": "/catalogs2/carservice",
        "children": []
      },
      {
        "id": 69,
        "title": "Расходные материалы",
        "link": "/catalogs2/tools-consumables"
      },
      {
        "id": 58,
        "title": "Автолитература",
        "link": "/catalogs2/other-books"
      },
      {
        "id": 16,
        "title": "Сувенирная продукция",
        "link": "/catalogs2/other-suvenir"
      },
      {
        "id": 89,
        "title": "Лебёдки",
        "link": "/catalogs2/tools-winches"
      },
      {
        "id": 35,
        "title": "Остальное",
        "link": "/catalogs2/other-accessories"
      }
    ]
  }
]

Мне нужно записать ссылки и названия категорий в один столбец.
Сейчас я это реализовал тремя циклами, так как максимальная вложенность равна трем. Но меня все волнует вопрос, а что если это значение увеличится, неправильно делать так топорно.
Пришел к решению, что нужно через рекурсию. Но так и не понял как реализовать.

В VS для десериализации JSON я создал классы. Но насколько я понимаю, это не совсем верно, так как типы класса грубо говоря похожи, а значит Child1 можно опустить (← это моя догадка).
Классы для десериализации:
public class Rootobject
{
    [JsonProperty("Property1")]
    public Categories[] FullTree { get; set; }
}

public class Categories
{
    [JsonProperty("id")]
    public int Id { get; set; }
    [JsonProperty("title")]
    public string Title { get; set; }
    [JsonProperty("link")]
    public string Link { get; set; }
    [JsonProperty("children")]
    public Child[] Children { get; set; }
}

public class Child
{
    [JsonProperty("id")]
    public int Id { get; set; }
    [JsonProperty("title")]
    public string Title { get; set; }
    [JsonProperty("link")]
    public string Link { get; set; }
    [JsonProperty("children")]
    public Child1[] Children { get; set; }
}

public class Child1
{
    [JsonProperty("id")]
    public int Id { get; set; }
    [JsonProperty("title")]
    public string Title { get; set; }
    [JsonProperty("link")]
    public string Link { get; set; }
}
Подскажите, пожалуйста, что мне сделать, чтобы десереализовать любое количество вложенностей с выводом в один столбец?
 

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 787
Благодарностей
2 452
Баллы
113
Мне нужно записать ссылки и названия категорий в один столбец.
Возможно не самый хороший вариант (Вы хотели рекурсию, этот без рекурсии), но в целом задачу выполняет корректно.
C#:
string text = project.Variables["text"].Value.Trim(); // Json беру с переменной
project.Json.FromString(text); // Разбираю Json с переменной

List<string> list_out = new List<string>(); // Список для хранения результата
List<string[]> list = new List<string[]>(); // Временный список для хранения метки, ключа, значения

var dic = project.Json.GetAllMembersList(); // Получаю словарь ключей и значений
foreach(string variable in dic.Keys){
    string[] keys = variable.Split('.'); // Разбил ключ по значению
    if(keys.Length > 1) { // Исключаю Count
        string last = keys.Last(); // Получил link, title
        string first = (string.Join("|", keys.Take(keys.Length-1))).GetMD5Hash(); // получил оригинальный ключ для строки       
        if(last == "link" || last == "title" ) {
            list.Add(new[]{first, last, (string)dic[variable]}); // добавляю данные в список
        }
    }
}

List<string> temp = list.Select( x => x[0]).Distinct().ToList(); // Определяю пары title link
foreach(string key in temp) {
    List<string[]> data = list.Where( x => x[0] == key).ToList(); // Получаю одну пару из списка
    string title = data.Where(x=>x[1] == "title").First()[2]; // Извлекаю title
    string link = data.Where(x=>x[1] == "link").First()[2]; // Извлекаю link
    list_out.Add(string.Format("{0} {1}", title, link)); // Добавляю результат в список
}

foreach(string s in list_out) project.SendInfoToLog(s); // Вывожу результат в лог
90207
 

djaga

Administrator
Команда форума
Регистрация
26.04.2020
Сообщения
546
Благодарностей
1 125
Баллы
93
@BAZAg Привет. Нашел как решить через рекурсию. Надеюсь это решение поможет не только мне, но сообществу.)

JavaScript:
[
{
"id": 3,
"title": "Шины и диски",
"link": "/catalogs2/3",
"children": [
{
"id": 201,
"title": "Шины",
"link": "/catalogs2/201"
},
{
"id": 202,
"title": "Диски",
"link": "/catalogs2/202"
},
{
"id": 86,
"title": "Камеры",
"link": "/catalogs2/wheelcamera"
}
]
},
{
"id": 4,
"title": "Масла и автохимия",
"link": "/catalogs2/4",
"children": [
{
"id": 41,
"title": "Масла",
"link": "/catalogs2/41",
"children": [
{
"id": 211,
"title": "гидравлические",
"link": "/catalogs2/211"
},
{
"id": 212,
"title": "моторные",
"link": "/catalogs2/212"
},
{
"id": 213,
"title": "индустриальные редукторные",
"link": "/catalogs2/213"
},
{
"id": 214,
"title": "промывочные",
"link": "/catalogs2/214"
},
{
"id": 215,
"title": "трансмиссионные",
"link": "/catalogs2/215"
},
{
"id": 75,
"title": "амортизационные",
"link": "/catalogs2/fluids-amortization"
}
]
},
{
"id": 42,
"title": "Жидкости",
"link": "/catalogs2/42",
"children": [
{
"id": 216,
"title": "AdBlue",
"link": "/catalogs2/216"
},
{
"id": 217,
"title": "охлаждающие",
"link": "/catalogs2/217"
},
{
"id": 218,
"title": "стеклоомывателя",
"link": "/catalogs2/218"
},
{
"id": 219,
"title": "тормозные",
"link": "/catalogs2/219"
}
]
},
{
"id": 43,
"title": "Присадки",
"link": "/catalogs2/43",
"children": [
{
"id": 220,
"title": "в масла",
"link": "/catalogs2/220"
},
{
"id": 221,
"title": "в систему охлаждения",
"link": "/catalogs2/221"
},
{
"id": 222,
"title": "топливные",
"link": "/catalogs2/222"
}
]
},
{
"id": 255,
"title": "Смазки",
"link": "/catalogs2/255"
},
{
"id": 281,
"title": "Уход и очистка",
"link": "/catalogs2/281"
},
{
"id": 24,
"title": "Автокосметика",
"link": "/catalogs2/cosmetic"
},
{
"id": 26,
"title": "Остальное",
"link": "/catalogs2/chemistry"
}
]
},
{
"id": 5,
"title": "Электрооборудование",
"link": "/catalogs2/5",
"children": [
{
"id": 231,
"title": "Аккумуляторы",
"link": "/catalogs2/231"
},
{
"id": 232,
"title": "Батарейки",
"link": "/catalogs2/232"
},
{
"id": 233,
"title": "Лампы",
"link": "/catalogs2/233"
},
{
"id": 246,
"title": "Мойки высокого давления",
"link": "/catalogs2/246"
},
{
"id": 249,
"title": "Подметальные машины",
"link": "/catalogs2/249"
},
{
"id": 269,
"title": "Провода пусковые",
"link": "/catalogs2/269"
},
{
"id": 263,
"title": "Пылесосы",
"link": "/catalogs2/263"
},
{
"id": 250,
"title": "Устройства пуско-зарядные",
"link": "/catalogs2/250"
},
{
"id": 38,
"title": "Компрессоры, насосы и манометры",
"link": "/catalogs2/electro-compressors"
},
{
"id": 52,
"title": "Видеорегистраторы",
"link": "/catalogs2/electro-dvrs"
},
{
"id": 47,
"title": "Автозвук",
"link": "/catalogs2/electro-sound"
},
{
"id": 55,
"title": "Парковочные радары и камеры",
"link": "/catalogs2/electro-parktronic"
},
{
"id": 54,
"title": "Противоугонные устройства",
"link": "/catalogs2/electro-alarms"
},
{
"id": 44,
"title": "Подогреватели двигателя",
"link": "/catalogs2/electro-engineheater"
},
{
"id": 56,
"title": "Радар-детекторы",
"link": "/catalogs2/electro-detectors"
},
{
"id": 41,
"title": "Остальное",
"link": "/catalogs2/electro-autoelectronics"
}
]
},
{
"id": 6,
"title": "Инструменты",
"link": "/catalogs2/6",
"children": [
{
"id": 252,
"title": "Головки торцевые",
"link": "/catalogs2/252"
},
{
"id": 241,
"title": "Домкраты",
"link": "/catalogs2/241"
},
{
"id": 243,
"title": "Ключи баллонные",
"link": "/catalogs2/243"
},
{
"id": 247,
"title": "Наборы инструментов",
"link": "/catalogs2/247"
},
{
"id": 248,
"title": "Отвёртки",
"link": "/catalogs2/248"
},
{
"id": 256,
"title": "Хомуты",
"link": "/catalogs2/256"
},
{
"id": 70,
"title": "Ручной инструмент",
"link": "/catalogs2/tools-hand"
},
{
"id": 38,
"title": "Компрессоры, насосы и манометры",
"link": "/catalogs2/electro-compressors"
},
{
"id": 72,
"title": "Электроинструмент",
"link": "/catalogs2/tools-power"
},
{
"id": 74,
"title": "Пневмоинструмент",
"link": "/catalogs2/tools-pneumatic"
},
{
"id": 67,
"title": "Измерительный инстр.",
"link": "/catalogs2/tools-measuring"
},
{
"id": 71,
"title": "Хранение инструмента",
"link": "/catalogs2/tools-storage"
}
]
},
{
"id": 7,
"title": "Интерьер",
"link": "/catalogs2/7",
"children": [
{
"id": 224,
"title": "Ароматизаторы",
"link": "/catalogs2/224"
},
{
"id": 263,
"title": "Пылесосы",
"link": "/catalogs2/263"
},
{
"id": 266,
"title": "Накидки с обогревом",
"link": "/catalogs2/266"
},
{
"id": 267,
"title": "Оплётки на руль",
"link": "/catalogs2/267"
},
{
"id": 32,
"title": "Коврики",
"link": "/catalogs2/other-carpets"
},
{
"id": 33,
"title": "Чехлы и накидки",
"link": "/catalogs2/other-covers"
},
{
"id": 43,
"title": "Автокресла",
"link": "/catalogs2/other-seat"
},
{
"id": 42,
"title": "Держатели и столики",
"link": "/catalogs2/other-holders"
}
]
},
{
"id": 8,
"title": "Экстерьер",
"link": "/catalogs2/8",
"children": [
{
"id": 60,
"title": "Дефлекторы",
"link": "/catalogs2/other-deflectors"
},
{
"id": 29,
"title": "Защита на автомобиль",
"link": "/catalogs2/other-protection"
},
{
"id": 30,
"title": "Фаркопы",
"link": "/catalogs2/other-towbar"
},
{
"id": 59,
"title": "Багажные системы",
"link": "/catalogs2/other-baggage"
},
{
"id": 28,
"title": "Внешний декор",
"link": "/catalogs2/decor"
},
{
"id": 272,
"title": "Щётки стеклоочистителя",
"link": "/catalogs2/272"
}
]
},
{
"id": 9,
"title": "Остальное",
"link": "/catalogs2/9",
"children": [
{
"id": 262,
"title": "Автоодеяла",
"link": "/catalogs2/262"
},
{
"id": 90,
"title": "Защита и гигиена",
"link": "/catalogs2/medicine",
"children": []
},
{
"id": 264,
"title": "Велосипеды",
"link": "/catalogs2/264"
},
{
"id": 251,
"title": "Герметики",
"link": "/catalogs2/251"
},
{
"id": 265,
"title": "Жилеты светоотражающие сигнальные",
"link": "/catalogs2/265"
},
{
"id": 253,
"title": "Клеи",
"link": "/catalogs2/253"
},
{
"id": 242,
"title": "Канистры",
"link": "/catalogs2/242"
},
{
"id": 268,
"title": "Очистка от снега, льда и воды",
"link": "/catalogs2/268"
},
{
"id": 254,
"title": "Ремни поликлиновые",
"link": "/catalogs2/254"
},
{
"id": 271,
"title": "Светофильтры",
"link": "/catalogs2/271"
},
{
"id": 65,
"title": "Для автосервиса",
"link": "/catalogs2/carservice",
"children": []
},
{
"id": 69,
"title": "Расходные материалы",
"link": "/catalogs2/tools-consumables"
},
{
"id": 58,
"title": "Автолитература",
"link": "/catalogs2/other-books"
},
{
"id": 16,
"title": "Сувенирная продукция",
"link": "/catalogs2/other-suvenir"
},
{
"id": 89,
"title": "Лебёдки",
"link": "/catalogs2/tools-winches"
},
{
"id": 35,
"title": "Остальное",
"link": "/catalogs2/other-accessories"
}
]
}
]
Вернуть одноуровневый List из многоуровневого array JSON:
public List<string> Format(Child root)
{
    var items = Unwrap(root);
    return (from item in items where item != null select $"{item.Title} || {item.Link}").ToList();
}

private List<Child?> Unwrap(Child? parent)
{
    var result = new List<Child?> { parent };
    if (parent.Children == null) return result;
    foreach (var child in parent.Children) { result.AddRange(Unwrap(child)); }

    return result;
}
 

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)