При интеграции баз данных 1С со сторонними системами или сайтами часто возникает задача выгрузить справочник с сохранением иерархии групп и элементов в формат JSON. Начинающие разработчики нередко пытаются решить эту задачу "в лоб" с помощью рекурсии, передавая структуру на каждый уровень вложенности. Рассмотрим подробнее типичные проблемы такого подхода и разберем по шагам, как правильно и оптимально выгрузить древовидные данные.
Проанализируем ситуацию, когда при обходе папок справочника программа зависает или на выходе формируется JSON с неверными данными. Истинная причина кроется в архитектурных ошибках и непонимании работы платформы 1С с памятью.
Новый Структура один раз перед вызовом функции, а затем передаем ее в рекурсию, то на всех уровнях вложенности мы модифицируем один и тот же объект в памяти. Ключи структуры постоянно перезаписываются данными самого глубокого уровня вложенности. Из-за этого кажется, что данные теряются или рекурсия зацикливается. Чтобы иерархия строилась корректно, необходимо для каждой новой папки инициализировать новую структуру внутри рекурсии.Разберем, как избавиться от множественных запросов. Для получения всего дерева за один раз необходимо написать один запрос к справочнику с использованием конструкции ИТОГИ ПО Родитель ТОЛЬКО ИЕРАРХИЯ.
После выполнения такого запроса результат нужно обходить специальным образом, используя метод ПоГруппировкам. Посмотрим на пример:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.ЭтоГруппа КАК ЭтоГруппа,
| Номенклатура.Родитель КАК Родитель
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.ПометкаУдаления = ЛОЖЬ
|ИТОГИ ПО
| Родитель ТОЛЬКО ИЕРАРХИЯ";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаГрупп = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
// Далее пишем рекурсивную функцию для обхода уже полученной выборки
В этом случае наша рекурсивная функция будет обходить не базу данных, а уже сформированную выборку в оперативной памяти. Это работает моментально.
Использование объектной модели (когда мы собираем всё дерево в огромную структуру или массив, а затем разом передаем в ЗаписатьJSON) при выгрузке большого справочника может привести к перерасходу оперативной памяти.
Лучшая практика — это потоковая запись JSON. Вместо формирования громоздких структур, в процессе обхода выборки мы напрямую вызываем методы объекта ЗаписьJSON. Проанализируем, как это выглядит:
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
// Внутри обхода выборки вызываем методы записи
ЗаписьJSON.ЗаписатьНачалоОбъекта();
ЗаписьJSON.ЗаписатьИмяСвойства("Group");
ЗаписьJSON.ЗаписатьЗначение(Строка(Выборка.Ссылка));
ЗаписьJSON.ЗаписатьИмяСвойства("Nomencl");
ЗаписьJSON.ЗаписатьНачалоМассива();
// ... запись элементов ...
ЗаписьJSON.ЗаписатьКонецМассива();
ЗаписьJSON.ЗаписатьКонецОбъекта();
Этот подход последовательно пишет данные, практически не потребляя оперативную память, что делает вашу обработку стабильной при любых объемах номенклатуры.
Если цель задачи — выгрузить данные для другой базы 1С, ручное формирование структур можно вообще исключить.
ДеревоЗначений методом Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией). Написать рекурсивный обход строк готового дерева в памяти гораздо безопаснее.СериализаторXDTO, который умеет автоматически выгружать ссылки и объекты (справочники, документы) в формат JSON со всеми реквизитами. Достаточно выгрузить нужные элементы в массив и передать их сериализатору, который сам развернет поля согласно метаданным вашей конфигурации.Применяя эти методы, вы избежите зависаний рекурсии, исключите лишнюю нагрузку на сервер БД и сделаете ваш код надежным и эффективным.