Как сохранить имя тега элемента коллекции при сериализации XDTO в JSON?

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

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

Проблема: исчезновение имен узлов в массиве

Рассмотрим классическую ситуацию. У нас есть XDTO-пакет, в котором определена коллекция (например, табличная часть). В XML-представлении это выглядит логично:


<ТЧ_ИзменениеКоллекции>
    <Строка>
        <Дата>2001-01-01T00:00:00</Дата>
        <Коллекция>НоваяКоллекция</Коллекция>
    </Строка>
    <Строка>
        <Дата>2017-04-01T00:00:00</Дата>
        <Коллекция>Сток</Коллекция>
    </Строка>
</ТЧ_ИзменениеКоллекции>

Однако при выполнении стандартного кода сериализации в JSON ситуация меняется:


ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыЗаписи = Новый ПараметрыЗаписиJSON(,,,,Истина,Истина,Истина,Истина,Истина);
ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписи);
МояФабрикаXDTO.ЗаписатьJSON(ЗаписьJSON, МоиДанные, НазначениеТипаXML.Явное);
Результат = ЗаписьJSON.Закрыть();

На выходе мы получаем структуру, где имя тега Строка полностью отсутствует:


"ТЧ_ИзменениеКоллекции": [
    { "Дата": "2001-01-01T00:00:00", "Коллекция": "НоваяКоллекция" },
    { "Дата": "2017-04-01T00:00:00", "Коллекция": "Сток" }
]

Для сторонних систем, ожидающих строгого соответствия (например, "Строка": {...} внутри массива), такой формат может оказаться неприемлемым. Выясним причину такого поведения платформы.

Анализируем логику платформы 1С

Разберем, почему 1С ведет себя именно так. В формате XML не существует понятия «массив» в том виде, в котором он есть в языках программирования. Чтобы передать список элементов, XML вынужден повторять имя узла (в нашем примере это Строка). В формате JSON, напротив, массивы являются базовой конструкцией. Платформа 1С при чтении схемы XDTO видит свойство с параметром MaxOccurs > 1 и понимает, что перед ней коллекция. При записи в JSON она интерпретирует имя родительского свойства (ТЧ_ИзменениеКоллекции) как ключ массива, а сами элементы вкладывает в массив напрямую, считая промежуточный тег Строка избыточным «техническим» мусором.

Тем не менее, если требования протокола обмена жестко задают наличие вложенного ключа, нам придется прибегнуть к одному из следующих решений.

Решение №1: Изменение схемы XDTO (Метод «Обертка»)

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

  1. Создадим в схеме новый ТипОбъекта, назовем его, например, ЭлементСпискаСтрок.
  2. Внутри этого типа добавим единственное свойство с именем Строка. Типом этого свойства должен быть ваш исходный тип данных (с датой и коллекцией).
  3. В основном объекте (где находится ТЧ_ИзменениеКоллекции) укажем, что элементами списка являются объекты типа ЭлементСпискаСтрок.

В этом случае при сериализации в JSON платформа увидит массив объектов. Каждый объект массива будет иметь свойство Строка. Итоговый файл примет нужный вид:


"ТЧ_ИзменениеКоллекции": [
    { "Строка": { "Дата": "...", "Коллекция": "..." } },
    { "Строка": { "Дата": "...", "Коллекция": "..." } }
]

Решение №2: Программная конвертация в Универсальные коллекции

Если изменять схему XDTO нельзя (например, она предоставлена внешним контрагентом), мы можем преобразовать данные вручную перед записью в JSON. Для этого нам потребуется переложить данные из объекта XDTO в Массив и Структуры (или Соответствия).

Рассмотрим пример кода для такой трансформации:


// Создаем массив, который станет основой JSON-списка
СписокДляJSON = Новый Массив;

// Обходим данные из XDTO-объекта
Для Каждого ЭлементXDTO Из МоиДанные.ТЧ_ИзменениеКоллекции Цикл
    
    // Для каждого элемента создаем структуру-обертку с нужным ключом
    Обертка = Новый Структура;
    
    // Наполняем данными самого элемента
    ДанныеЭлемента = Новый Структура;
    ДанныеЭлемента.Вставить("Дата", ЭлементXDTO.Дата);
    ДанныеЭлемента.Вставить("Коллекция", ЭлементXDTO.Коллекция);
    
    // Вкладываем данные в обертку под ключом "Строка"
    Обертка.Вставить("Строка", ДанныеЭлемента);
    
    // Добавляем в общий массив
    СписокДляJSON.Добавить(Обертка);
    
КонецЦикла;

// Теперь упаковываем все это в итоговую структуру
ИтоговаяСтруктура = Новый Структура;
ИтоговаяСтруктура.Вставить("ТЧ_ИзменениеКоллекции", СписокДляJSON);

// Записываем полученную структуру в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ИтоговаяСтруктура);
Результат = ЗаписьJSON.Закрыть();

Этот метод дает полный контроль над именами полей, но требует написания дополнительного кода для обхода всех уровней вложенности объекта.

Решение №3: Использование «грязного» хака с пост-обработкой текста

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

Выводы и рекомендации

Подводя итог, можно сказать, что «исчезновение» тегов — это не ошибка 1С, а следование стандартам JSON, где массивы не требуют именования каждого элемента. Если же вам жизненно необходимо сохранить структуру "ИмяТега": { ... } внутри массива:

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

← На главную