Как сериализовать структуру 1С в JSON-объект вместо массива и сохранить ссылки

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

При разработке интеграций между 1С и внешними системами программисты часто сталкиваются с особенностью работы встроенного механизма СериализаторXDTO. Вместо ожидаемого компактного JSON-объекта на выходе получается громоздкая структура с техническими полями типа #value, name и Value. В этой статье мы разберем, почему так происходит, и рассмотрим несколько способов получения «красивого» JSON, который будет удобен для принимающей стороны и пригоден для обратной десериализации.

Выясняем причину: почему СериализаторXDTO превращает структуру в массив

Давайте проанализируем ситуацию. Когда мы используем СериализаторXDTO.ЗаписатьJSON, платформа 1С строго следует описанию типов XDTO. В канонической схеме 1С объект Структура представляется именно как список пар «ключ-значение». Это сделано для обеспечения универсальности: ключи структуры в 1С могут содержать символы, которые недопустимы в качестве имен свойств в классическом JSON без специального экранирования. Чтобы гарантировать корректность данных в любом случае, XDTO-сериализатор выбирает наиболее надежный, но «некрасивый» формат массива.

Рассмотрим пример кода, который вызывает проблему:


Структура = Новый Структура;
Структура.Вставить("НомерСообщения", 1);
Структура.Вставить("МассивДанных", МассивСсылок); // Массив со ссылками на справочники
СериализаторXDTO.ЗаписатьJSON(ЗаписьJSON, Структура, НазначениеТипаXML.Явное);

На выходе мы получаем технический дамп, где свойства объекта 1С упакованы в элементы массива. Принимающей стороне (например, веб-приложению на JavaScript) крайне неудобно разбирать такие конструкции. Им нужен объект вида {"НомерСообщения": 1, "МассивДанных": [...]}.

Решение №1: Использование глобальной функции ЗаписатьJSON с функцией преобразования

Наиболее эффективный и гибкий способ — отказаться от прямой записи через СериализаторXDTO в пользу глобальной функции ЗаписатьJSON. Однако здесь возникает препятствие: стандартная функция умеет работать только с примитивными типами (строки, числа, булево). Если в структуре попадется СправочникСсылка или ДокументСсылка, система выдаст ошибку.

Для решения этой задачи мы воспользуемся параметром ИмяФункцииПреобразования. Это позволит нам сохранить «красивый» вид структуры и при этом корректно обработать сложные типы 1С.

Разберем реализацию по шагам:

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

Пример функции преобразования:


Функция ПреобразоватьДанныеВJSON(Свойство, Значение, ДополнительныеПараметры, Отказ) Экспорт
    
    // Если тип значения — ссылка, преобразуем её в структуру или строку ГУИД
    Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
        Возврат Строка(Значение.УникальныйИдентификатор());
    ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипЗнч(Значение)) Тогда
        Возврат Строка(Значение.УникальныйИдентификатор());
    КонецЕсли;
    
    // Если тип неизвестен, оставляем как есть или выдаем ошибку
    Возврат Значение;
    
КонецФункции

Теперь вызовем сериализацию:


ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
// Указываем имя функции преобразования, которая находится в общем модуле "ИнтеграцияСервер"
ЗаписатьJSON(ЗаписьJSON, Структура, , "ИнтеграцияСервер.ПреобразоватьДанныеВJSON");
Результат = ЗаписьJSON.Закрыть();

Решение №2: Предварительная «канонизация» данных (подготовка структуры)

Если нам нужно передать не просто идентификатор (GUID), а полноценные данные объекта (код, наименование, реквизиты) в виде JSON-объекта, мы можем применить метод предварительной подготовки. Рассмотрим этот подход подробнее.

Вместо того чтобы передавать массив ссылок, мы создадим массив структур. Каждая структура будет представлять собой «слепок» объекта 1С. Этот метод гарантирует, что на выходе будет чистый JSON, понятный любой внешней системе.

Проанализируем пример кода для подготовки данных:


// Подготовим массив для сериализации
МассивОбъектовДляЭкспорта = Новый Массив;

Для Каждого СсылкаИзСписка Из МассивСсылок Цикл
    
    ДанныеОбъекта = Новый Структура;
    ДанныеОбъекта.Вставить("Ref", Строка(СсылкаИзСписка.УникальныйИдентификатор()));
    ДанныеОбъекта.Вставить("Description", СсылкаИзСписка.Наименование);
    ДанныеОбъекта.Вставить("Code", СсылкаИзСписка.Код);
    
    // Если есть дополнительные реквизиты
    ДанныеОбъекта.Вставить("Price", СсылкаИзСписка.Цена);
    
    МассивОбъектовДляЭкспорта.Добавить(ДанныеОбъекта);
    
КонецЦикла;

// Формируем итоговую структуру
ИтоговаяСтруктура = Новый Структура;
ИтоговаяСтруктура.Вставить("НомерСообщения", 1);
ИтоговаяСтруктура.Вставить("МассивДанных", МассивОбъектовДляЭкспорта);

// Теперь обычный ЗаписатьJSON отработает идеально
ЗаписатьJSON(ЗаписьJSON, ИтоговаяСтруктура);

Преимущество этого метода: Вы полностью контролируете состав передаваемых данных и формат имен полей (например, можно использовать camelCase, принятый в веб-разработке).

Решение №3: Комбинированный метод (XDTO внутри ЗаписатьJSON)

Если на принимающей стороне тоже находится 1С, и вам критически важно сохранить возможность автоматической десериализации обратно в объекты 1С, можно использовать хитрость. В функции преобразования (которую мы рассматривали в первом решении) можно программно вызывать СериализаторXDTO.ЗаписатьXDTO() для конкретного объекта.

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

Важно помнить: СериализаторXDTO всегда будет стремиться к избыточности ради типизации. Если ваша задача — просто передать данные, используйте Решение №2. Если задача — синхронизация баз 1С, то стандартный формат СериализаторXDTO.ЗаписатьJSON (даже в виде массива) будет наиболее правильным выбором, так как он минимизирует ошибки при восстановлении типов.

Подводим итоги

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

Такой подход делает ваши интеграционные механизмы более профессиональными, а код — понятным для разработчиков на других платформах.

← На главную