В современной разработке часто возникает задача передачи данных из 1С во внешние системы (веб-сайты, мобильные приложения, сторонние API). Одной из наиболее трудоемких задач является сохранение древовидной структуры иерархических справочников при конвертации в формат JSON. В этой статье мы подробно разберем, как правильно сформировать вложенный JSON, чтобы структура "Папка - Подпапка - Элемент" сохранилась в исходном виде.
Это классический и наиболее гибкий способ. Его суть заключается в том, что мы сначала получаем данные из 1С в виде системного объекта ДеревоЗначений, который уже содержит иерархию, а затем рекурсивно обходим его для формирования структуры JSON. Рассмотрим этот процесс пошагово.
Шаг 1: Получение данных. Для начала нам необходимо составить запрос, который выберет элементы справочника с учетом их подчиненности. Важно использовать итоги по иерархии, чтобы платформа сама выстроила дерево.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование,
| Номенклатура.ЭтоГруппа КАК ЭтоГруппа
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ИТОГИ ПО
| Ссылка ИЕРАРХИЯ";
Дерево = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);
Шаг 2: Рекурсивное преобразование. Теперь напишем функцию, которая будет превращать строки дерева значений в массив структур. Каждая структура будет представлять собой элемент справочника, а если у него есть вложенные элементы, они попадут в массив items внутри этой структуры.
Функция ДеревоВМассив(СтрокиДерева)
МассивРезультат = Новый Массив;
Для Каждого СтрокаДерева Из СтрокиДерева Цикл
СтруктураОбъекта = Новый Структура;
СтруктураОбъекта.Вставить("id", Строка(СтрокаДерева.Ссылка.УникальныйИдентификатор()));
СтруктураОбъекта.Вставить("name", СтрокаДерева.Наименование);
СтруктураОбъекта.Вставить("isFolder", СтрокаДерева.ЭтоГруппа);
// Рекурсивный вызов для подчиненных строк
Если СтрокаДерева.Строки.Количество() > 0 Тогда
СтруктураОбъекта.Вставить("items", ДеревоВМассив(СтрокаДерева.Строки));
Иначе
СтруктураОбъекта.Вставить("items", Новый Массив);
КонецЕсли;
МассивРезультат.Добавить(СтруктураОбъекта);
КонецЦикла;
Возврат МассивРезультат;
КонецФункции
Шаг 3: Запись в JSON. Полученный массив структур легко сериализуется стандартными средствами платформы.
РезультатМассив = ДеревоВМассив(Дерево.Строки);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, РезультатМассив);
ИтоговаяСтрока = ЗаписьJSON.Закрыть();
Если справочник очень большой, рекурсивный обход дерева может работать медленно или вызывать избыточную нагрузку на память. В таких случаях мы проанализируем альтернативный подход — "сборка снизу вверх" с использованием объекта Соответствие.
Алгоритм действий следующий:
Структура, где будут храниться его данные и пустой массив для будущих детей.Соответствие, где ключом выступает Ссылка элемента.Этот метод позволяет избежать рекурсии и собрать дерево за фиксированное время, пропорциональное количеству элементов.
При выгрузке в JSON мы часто сталкиваемся с тем, что стандартная функция ЗаписатьJSON не знает, как обрабатывать специфические типы, такие как СправочникСсылка или УникальныйИдентификатор. Разберем, как решить эту проблему.
Проанализируем использование параметров сериализации. Мы можем передать в функцию ЗаписатьJSON специальный объект НастройкиСериализацииJSON. В этих настройках можно указать имя функции-обработчика, которая будет вызываться каждый раз, когда сериализатор встречает "непонятный" ему тип.
Настройки = Новый НастройкиСериализацииJSON;
Настройки.ВариантЗаписиДаты = ВариантЗаписиДатыJSON.ISO;
// Пример обработки ссылки
// В коде функции-обработчика:
// Если ТипЗнч(Значение) = Тип("СправочникСсылка.Номенклатура") Тогда
// Возврат Строка(Значение.УникальныйИдентификатор());
// КонецЕсли;
Важный момент: всегда приводите ссылки к строковому представлению их GUID. Если просто передать ссылку в структуру, сериализатор может выдать системную строку вида {"Ref": "..."}, что не всегда удобно для внешних систем.
Стоит рассмотреть ситуацию, когда принимающая сторона (например, современный веб-фронтенд на React или Vue) предпочитает получать не вложенную структуру, а плоский массив объектов. В этом случае каждый объект должен содержать поля id и parentId.
Выясним преимущества такого подхода:
Для реализации этого метода достаточно выгрузить результат запроса в таблицу значений и сериализовать её как массив структур, не заботясь о вложенности на стороне 1С.
При работе с иерархией в 1С (особенно в старых базах или после некорректных обменов) возможна ситуация "зацикливания", когда элемент является родителем самого себя. Рассмотрим, как этого избежать. При использовании рекурсивного метода 1 (через ДеревоЗначений) платформа сама контролирует иерархию, и бесконечный цикл маловероятен. Однако при ручной сборке дерева рекомендуется вести список уже обработанных ссылок. Если ссылка встречается повторно в одной ветке — это сигнал о критической ошибке в данных, которую нужно обработать исключением или пропустить элемент.
Таким образом, мы разобрали основные способы формирования иерархического JSON. Выбор конкретного метода зависит от объема ваших данных и требований системы-потребителя. Для небольших справочников идеально подойдет рекурсия по дереву значений, а для высоконагруженных систем — сборка через соответствия или передача плоского списка.