При разработке механизмов интеграции программисты 1С часто сталкиваются с необходимостью формирования сложных, многоуровневых файлов в форматах JSON или XML. Когда структура файла становится громоздкой, поддерживать такой код становится трудно: визуально сложно определить, где заканчивается один объект и начинается другой. В этой статье мы разберем различные подходы к структурированию кода — от хитростей с логическими операторами до современных методов платформы 1С.
Основная сложность заключается в поведении встроенного редактора 1С. При использовании стандартного средства форматирования (клавиши Alt+Shift+F) редактор выравнивает все последовательные вызовы методов по левому краю. Рассмотрим стандартный код потоковой записи:
ЗаписьJson.ЗаписатьНачалоОбъекта();
ЗаписьJson.ЗаписатьИмяСвойства("header");
ЗаписьJson.ЗаписатьНачалоОбъекта();
ЗаписьJson.ЗаписатьИмяСвойства("id");
ЗаписьJson.ЗаписатьЗначение(Параметры.Идентификатор);
ЗаписьJson.ЗаписатьКонецОбъекта();
ЗаписьJson.ЗаписатьКонецОбъекта();
Проанализируем эту ситуацию: если таких уровней вложенности будет десять, код превратится в «полотно», в котором крайне легко допустить ошибку, забыв вызвать ЗаписатьКонецОбъекта() или ЗаписатьКонецМассива(). Ручные отступы пробелами не спасают, так как первое же автоматическое форматирование их удалит.
Один из известных приемов — использование фиктивного условия для принудительного создания отступов. Поскольку конфигуратор обязан делать отступ внутри блока Если ... КонецЕсли, разработчики используют конструкцию Если Истина Тогда. Рассмотрим, как преображается код при таком подходе:
ЗаписьJson.ЗаписатьНачалоОбъекта(); // Корневой объект
ЗаписьJson.ЗаписатьИмяСвойства("data");
Если Истина Тогда
ЗаписьJson.ЗаписатьНачалоОбъекта();
ЗаписьJson.ЗаписатьИмяСвойства("order_info");
Если Истина Тогда
ЗаписьJson.ЗаписатьНачалоОбъекта();
ЗаписьJson.ЗаписатьИмяСвойства("number");
ЗаписьJson.ЗаписатьЗначение("INV-100");
ЗаписьJson.ЗаписатьКонецОбъекта();
КонецЕсли;
ЗаписьJson.ЗаписатьКонецОбъекта();
КонецЕсли;
ЗаписьJson.ЗаписатьКонецОбъекта();
Преимущества метода:
Недостатки и критика:
Многие ведущие разработчики и аудиторы кода (например, при проверке на соответствие стандартам «1С») считают этот метод «плохим тоном» или code smell. Основной аргумент — использование синтаксических конструкций не по назначению. Другой разработчик, читая ваш код, может потратить время на поиск скрытого смысла в условии Если Истина, хотя оно там присутствует только ради красоты.
Выясним, когда ручная запись (Stream Writing) действительно необходима. Если объем данных невелик (например, передача параметров небольшого документа), гораздо эффективнее использовать объект Структура или Массив и последующую сериализацию.
Посмотрим на пример правильного формирования JSON через структуры:
ДанныеДляОтправки = Новый Структура;
ДанныеДляОтправки.Вставить("id", ДокументСсылка.Номер);
ДанныеДляОтправки.Вставить("date", ДокументСсылка.Дата);
МассивТоваров = Новый Массив;
Для Каждого СтрокаТЧ Из ДокументСсылка.Товары Цикл
ТоварОбъект = Новый Структура("sku, qty", СтрокаТЧ.Номенклатура.Код, СтрокаТЧ.Количество);
МассивТоваров.Добавить(ТоварОбъект);
КонецЦикла;
ДанныеДляОтправки.Вставить("items", МассивТоваров);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ДанныеДляОтправки);
РезультатСтрокой = ЗаписьJSON.Закрыть();
В данном случае иерархия объектов 1С (Структура внутри Структуры) естественным образом повторяет иерархию JSON, и никакие дополнительные ухищрения с отступами не требуются. Важно помнить: этот метод не подходит для формирования гигантских файлов (десятки мегабайт), так как вся структура сначала собирается в оперативной памяти, что может привести к ошибке Out of Memory.
Начиная с версии платформы 8.3.23, процесс стал еще проще. Появилась возможность использовать функцию ЗаписатьЗначениеJSON(), которая позволяет получить готовую строку буквально в одну команду, не создавая объект ЗаписьJSON вручную. Если ваша задача — быстро превратить массив структур в строку, используйте именно этот метод, чтобы не загромождать код лишними инициализациями.
Если специфика задачи все же требует использования ЗаписьJSON (например, при потоковой записи огромного файла в файл на диске), разберем, как сделать код чище без использования фиктивных условий:
ЗаписатьУзелКонтрагента(ЗаписьJSON, Контрагент). Это создаст естественную структуру и упростит отладку.Если Истина используйте комментарии в конце закрывающих методов, например: ЗаписьJson.ЗаписатьКонецОбъекта(); // Конец секции "Файлы".ОткрытьФайл() или УстановитьСтроку() у объекта ЗаписьJSON можно указать параметры отступов (объект ПараметрыЗаписиJSON). Это повлияет на читаемость результирующего файла, но не на код в конфигураторе.Резюме: Использование Если Истина Тогда — это допустимый, но нежелательный прием, который оправдан только в очень специфических задачах потоковой записи для визуального контроля вложенности. В большинстве современных задач 1С следует отдавать предпочтение формированию данных через Структуры/Массивы и штатную функцию ЗаписатьJSON().