При работе с технологией Конвертация данных 3.0 и форматом Enterprise Data разработчики часто сталкиваются с необходимостью передать дополнительные сведения, которые не предусмотрены стандартным составом свойств XDTO-пакета. Для этих целей в формате существует свойство AdditionalInfo. Однако попытка передать в него массив или вложенную структуру часто приводит к ошибкам платформы. В этой статье мы разберем, почему это происходит, и проанализируем наиболее эффективные способы решения данной задачи. Для базового знакомства с архитектурой обмена подойдёт руководство по Конвертации данных 3.0 и формату Enterprise Data.
Разберем ситуацию на примере. Предположим, мы пытаемся передать массив ссылок на упаковки номенклатуры, предварительно преобразовав их в объекты XDTO. Рассмотрим типичный код, который вызывает затруднения:
ДополнительныеДанные = Новый Структура;
МассивУпаковок = Новый Массив;
ПКО_Упаковки = ОбменДаннымиXDTOСервер.ПКОПоИмени(КомпонентыОбмена, "Справочник_Упаковки");
Пока Выборка.Следующий() Цикл
// Превращаем ссылку ИБ в объект XDTO по правилам конвертации
ДанныеПоПравилам = ОбменДаннымиXDTOСервер.ДанныеXDTOИзДанныхИБ(КомпонентыОбмена, Выборка.Ссылка, ПКО_Упаковки);
МассивУпаковок.Добавить(ДанныеПоПравилам);
КонецЦикла;
ДополнительныеДанные.Вставить("УпаковкиНоменклатуры", МассивУпаковок);
ДанныеXDTO.Вставить("AdditionalInfo", ДополнительныеДанные);
Проблема заключается в том, что свойство AdditionalInfo в схеме Enterprise Data обычно описывается типом v8:Structure. Этот тип в реализации 1С ожидает набор пар «Ключ-Значение», где значением должен выступать примитивный тип (строка, число, дата, булево). Когда мы пытаемся поместить туда Массив, содержащий ОбъектXDTO, механизм сериализации не находит описания этого вложенного типа внутри структуры и выдает ошибку. Система просто «не знает», как упаковать сложный объект в XML-поле, предназначенное для простых данных.
Проанализируем самый современный и надежный способ — использование формата JSON. Поскольку в AdditionalInfo мы гарантированно можем передать строку, мы можем «упаковать» наш массив в компактную JSON-строку на стороне источника и «распаковать» ее на стороне приемника. Это позволяет сохранить структуру данных любой вложенности.
Рассмотрим, как изменить код формирования данных:
// Формируем массив простых данных (например, структур с кодами или артикулами)
МассивДляПередачи = Новый Массив;
Пока Выборка.Следующий() Цикл
ИнфоОбУпаковке = Новый Структура("Код, Наименование", Выборка.Код, Выборка.Наименование);
МассивДляПередачи.Добавить(ИнфоОбУпаковке);
КонецЦикла;
// Сериализуем массив в JSON-строку
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, МассивДляПередачи);
СтрокаJSON = ЗаписьJSON.Закрыть();
// Помещаем строку в AdditionalInfo
ДополнительныеДанные = Новый Структура;
ДополнительныеДанные.Вставить("УпаковкиНоменклатурыJSON", СтрокаJSON);
ДанныеXDTO.Вставить("AdditionalInfo", ДополнительныеДанные);
Важный нюанс: В данном примере мы передаем не объекты XDTO, а простые структуры. Если вам необходимо передать именно результат работы ДанныеXDTOИзДанныхИБ, помните, что объекты XDTO напрямую не сериализуются через ЗаписатьJSON. В этом случае лучше передать ключевые реквизиты (УИД, Код) и найти/создать объекты уже на стороне приемника.
Если нам необходимо передать данные в формате XML внутри свойства, мы можем воспользоваться встроенным объектом СериализаторXDTO. Этот метод позволяет преобразовать любой объект 1С (включая массивы и структуры) в строку XML, которую понимает платформа.
Выясним, как реализовать этот подход:
// На стороне источника
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, МассивУпаковок);
СтрокаXML = ЗаписьXML.Закрыть();
ДополнительныеДанные = Новый Структура;
ДополнительныеДанные.Вставить("ДанныеВФорматеXML", СтрокаXML);
ДанныеXDTO.Вставить("AdditionalInfo", ДополнительныеДанные);
На стороне приемника в обработчике ПослеЗагрузки или ПередЗаписью вам потребуется выполнить обратную операцию с помощью метода СериализаторXDTO.ПрочитатьXML().
Если массив состоит из простых строк (например, только артикулы или коды), использование JSON или XML может быть избыточным. В таких ситуациях мы можем применить простую конкатенацию строк с разделителем.
Посмотрим на пример:
СписокКодов = "";
Для Каждого Элемент Из МассивКодов Цикл
СписокКодов = СписокКодов + Элемент + ";";
КонецЦикла;
ДополнительныеДанные = Новый Структура;
ДополнительныеДанные.Вставить("СписокКодов", СписокКодов);
ДанныеXDTO.Вставить("AdditionalInfo", ДополнительныеДанные);
На приемнике такая строка легко превращается обратно в массив с помощью функции СтрРазделить(Строка, ";").
Важно понимать, что при использовании любого из вышеперечисленных методов автоматического «развертывания» данных в объекты 1С не произойдет. Вам необходимо программно обработать содержимое AdditionalInfo в правилах конвертации объектов (ПКО). Для настройки соответствий объектов между базами можно использовать подход к формированию мэппинга в формате EnterpriseData.
Разберем алгоритм действий в обработчике ПослеЗагрузки:
ДополнительныеДанные.ЧтениеJSON и ПрочитатьJSON.СериализаторXDTO.ПрочитатьXML.Подводя итог, можно выделить следующие правила работы с AdditionalInfo в КД 3.0:
AdditionalInfo, так как это нарушает строгую типизацию XML-пакета.Таким образом, использование строковой сериализации (особенно JSON) является стандартным и общепринятым «обходным путем» в сообществе разработчиков 1С при работе с Конвертацией данных 3.0.