Как выгрузить вложенный объект в JSON из 1С: решаем проблему сериализации

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции 1С с внешними системами через API одной из самых частых задач становится формирование сложных JSON-пакетов с вложенными структурами. На первый взгляд задача кажется тривиальной: собрать данные в Соответствие или Структуру (например, используя Swagger) и вызвать метод ЗаписатьJSON. Однако на практике разработчики часто сталкиваются с ошибками на этапе записи, когда во вложенных объектах оказываются типы данных, специфичные для 1С, но «непонятные» формату JSON.

В этой статье мы подробно разберем, как правильно формировать вложенные объекты, почему возникают ошибки при сериализации и как автоматизировать процесс преобразования типов (используя конструктор API), чтобы ваш код был надежным и универсальным.

Выясним причину ошибки: почему 1С не записывает вложенный объект

Проанализируем типичную ситуацию (в этом поможет Python-коннектор к 1С). Допустим, нам нужно передать данные о номенклатуре, где поле «бренд» является отдельным объектом со своими свойствами (uid и name). Рассмотрим пример кода, который может вызвать затруднения:


ДанныеНоменклатуры = Новый Соответствие;
ДанныеНоменклатуры.Вставить("country", СсылкаНаОбъект.Производитель.Наименование);
// Пытаемся вставить вложенный объект
ДанныеНоменклатуры.Вставить("brand", СформироватьДанныеДляЗапросаПоБренду(СсылкаНаОбъект));

Функция СформироватьДанныеДляЗапросаПоБренду(СсылкаНаОбъект)
    ДанныеБренда = Новый Соответствие;
    // ОШИБКА ЗДЕСЬ: Прямая вставка уникального идентификатора
    ДанныеБренда.Вставить("uid", СсылкаНаОбъект.Марка.УникальныйИдентификатор());
    ДанныеБренда.Вставить("name", СсылкаНаОбъект.Марка.Наименование);
    Возврат ДанныеБренда;
КонецФункции

При попытке выполнить ЗаписатьJSON(ЗаписьJSON, ДанныеНоменклатуры) система выдаст ошибку. Проблема заключается в том, что стандартный метод платформы умеет работать только с ограниченным набором типов: Строка, Число, Булево, Дата, Массив, Структура и Соответствие. Тип УникальныйИдентификатор или любая Ссылка не входят в этот список и должны быть предварительно преобразованы.

Способ 1: Явное приведение типов (простой путь)

Самый быстрый способ решить проблему — привести все сложные значения к строковому виду (вот пример преобразования данных) непосредственно перед помещением в коллекцию. Рассмотрим подробнее, как изменить функцию формирования данных бренда, чтобы она стала валидной для JSON.

Вместо передачи объекта типа УникальныйИдентификатор, мы используем функцию Строка() или специализированную функцию XMLСтрока(). Последняя особенно полезна, так как она корректно работает со всеми ссылочными типами данных 1С.


Функция СформироватьДанныеДляЗапросаПоБренду(СсылкаНаОбъект)
    ДанныеБренда = Новый Соответствие;
    
    // Преобразуем идентификатор в строку явным образом
    ДанныеБренда.Вставить("uid", XMLСтрока(СсылкаНаОбъект.Марка)); 
    ДанныеБренда.Вставить("name", СсылкаНаОбъект.Марка.Наименование);
    
    Возврат ДанныеБренда;
КонецФункции

Теперь, когда во вложенном Соответствии содержатся только примитивные типы, метод ЗаписатьJSON отработает без ошибок, и мы получим корректную структуру объекта внутри JSON.

Способ 2: Использование функции обратного вызова (продвинутый путь)

Если вложенных объектов много, ручное преобразование каждого поля через Строка() становится трудоемким и засоряет код. Начиная с версии 8.3.6, платформа предлагает элегантное решение — параметр ФункцияОбратногоВызова в методе ЗаписатьJSON.

Разберем по шагам, как это работает. Если сериализатор встречает тип данных, который он не может обработать самостоятельно (например, перечисление или ссылку), он обращается к вашей функции. Мы можем написать универсальный обработчик:


// Основной код выгрузки
НастройкиСериализации = Новый НастройкиСериализацииJSON;
НастройкиСериализации.ВариантЗаписиДаты = ВариантЗаписиДатыJSON.ISO8601;

ЗаписатьJSON(ЗаписьJSON, ДанныеДляЗапроса, НастройкиСериализации, "МояФункцияПреобразования");

// Функция-обработчик «проблемных» типов
Функция МояФункцияПреобразования(Свойство, Значение, ДополнительныеПараметры, Отказ) Экспорт
    
    ТипЗначения = ТипЗнч(Значение);
    
    // Если это ссылка или идентификатор — превращаем в строку
    Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗначения) 
        Или ТипЗначения = Тип("УникальныйИдентификатор") Тогда
        Возврат XMLСтрока(Значение);
    ИначеЕсли Перечисления.ТипВсеСсылки().СодержитТип(ТипЗначения) Тогда
        Возврат Строка(Значение); // Или имя значения перечисления
    КонецЕсли;
    
    // Если мы не знаем, что делать, флаг Отказ оставит стандартную обработку (вызовет ошибку)
    Возврат Значение;
    
КонецФункции

Использование обработчика позволяет нам собирать вложенные Соответствия, не задумываясь о типах внутри. Платформа сама «позовет» нашу функцию, когда дойдет до вложенного объекта brand и его поля uid.

Разберем разницу между Структурой и Соответствием

При формировании вложенных объектов важно правильно выбрать тип коллекции. Часто программисты используют Структуру, но у нее есть два существенных ограничения для JSON:

  1. Имена ключей: Ключ структуры в 1С должен соответствовать правилам именования переменных (никаких пробелов, дефисов или спецсимволов). Если внешнее API требует ключ @id или brand-name, Структура не подойдет.
  2. Порядок полей: 1С не гарантирует сохранение порядка ключей в Структуре при выгрузке.

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

Проанализируем работу с датами во вложенных объектах

Дата — еще один тип, который часто вызывает вопросы при вложении объектов. По умолчанию 1С может выгружать дату в специфическом формате. Чтобы вложенные объекты содержали даты в стандарте ISO 8601 (принятом в большинстве веб-сервисов), необходимо использовать объект НастройкиСериализацииJSON.


Настройки = Новый НастройкиСериализацииJSON;
Настройки.ВариантЗаписиДаты = ВариантЗаписиДатыJSON.ISO8601;

// Теперь во всех вложенных структурах даты будут вида "2023-10-25T12:00:00"
ЗаписатьJSON(ЗаписьJSON, СформированныеДанные, Настройки);

Особенности сериализации XDTO

Иногда в контексте JSON упоминается СериализаторXDTO. Это мощный инструмент, который может выгрузить объект 1С (например, весь справочник) одной командой. Однако помните: СериализаторXDTO часто добавляет много лишней технической информации (типы данных, пространства имен), что может быть неприемлемо для простых REST API. Для передачи конкретных полей во вложенных объектах лучше использовать ручную сборку через Соответствие и метод ЗаписатьJSON, как мы рассмотрели выше.

Резюме для правильной выгрузки

Подводя итог, проанализируем основные правила успешной выгрузки вложенных объектов:

Следуя этим правилам, вы сможете формировать вложенные объекты любой сложности, обеспечивая корректную передачу данных между 1С и внешними информационными системами.

← На главную