Как установить тип объекта в XDTO и исправить ошибку несоответствия типов

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

При работе с интеграциями, особенно когда речь идет о государственных сервисах вроде СМЭВ Росздравнадзора, программисты 1С часто сталкиваются с ошибкой: "Несоответствие типов XDTO: Значение не может быть установлено свойству, имеющему объектный тип". Эта ситуация возникает, когда мы пытаемся записать простое значение (например, дату или строку) напрямую в свойство, которое по схеме XSD является сложным типом (объектом). Рассмотрим подробно, как правильно работать с такими структурами.

Выясняем причину ошибки

Проанализируем ситуацию: у нас есть свойство, например, ManufactureDate. Мы привыкли, что дата — это простой тип xs:date. Однако в сложных схемах дата может быть описана как DateInfoType. Если мы заглянем внутрь этого типа, то увидим, что это не просто поле, а целая структура (часто типа Choice — выбор), которая может содержать либо точную дату, либо период, либо описание длительности.

Попытка выполнить код типа ОбъектXDTO.ManufactureDate = ТекущаяДата() приведет к ошибке, так как 1С ожидает, что вы передадите в ManufactureDate целый объект, созданный по правилам DateInfoType, а не примитивное значение. Нам нужно сначала сконструировать этот "вложенный" объект, заполнить его внутренние реквизиты и только потом "вставить" его в родительское свойство.

Пошаговое решение задачи

Рассмотрим по шагам, как правильно создать и заполнить объектный тип в XDTO на примере интеграции с системой мониторинга медицинских изделий.

Шаг 1. Получение пакета и создание основного объекта

Прежде всего, нам нужно получить доступ к пространству имен (Namespace) и создать корневой объект сообщения. Посмотрим на пример кода:


// Получаем пакет по его URI
Пакет = ФабрикаXDTO.Пакеты.Получить("urn://smev-roszdravnadzor-ru/EPGU/MedDevicesCirculationInfo/1.0.0");

// Создаем корневой объект (например, BatchInfo)
ДокXDTO = ФабрикаXDTO.Создать(Пакет.КорневыеСвойства.Получить("BatchInfo").Тип);

Шаг 2. Создание вложенного сложного объекта

Теперь создадим объект для свойства, которое вызвало ошибку. Вместо прямого присваивания даты, мы создаем объект типа DateInfoType.


// Создаем объект вложенного типа
ОбъектДата = ФабрикаXDTO.Создать(Пакет.Получить("DateInfoType"));

// Заполняем внутреннее свойство этого объекта (именно оно имеет простой тип Дата)
ОбъектДата.Date = СтрокаДанных.ДатаПроизводства;

// Теперь присваиваем заполненный объект свойству родительского документа
ДокMedDevices.ManufactureDate = ОбъектДата;

Разбор комплексного типа (Choice)

Тип DateInfoType в схемах СМЭВ часто является гибким. Разберем подробнее, из чего он может состоять согласно документации. Это поможет нам понять, почему нельзя просто передать дату. Внутри него могут быть поля:

Когда мы создаем объект через ФабрикаXDTO.Создать, мы получаем возможность выбрать, какое именно из этих полей заполнить в соответствии с бизнес-логикой нашей задачи.

Полный пример реализации выгрузки

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


// Инициализация фабрики и создание основного уведомления
ДокNotification = ФабрикаXDTO.Создать(Пакет.Получить("NotificationInfoType"));
ДокNotification.NotificationId = СериализаторXDTO.XMLСтрока(Объект.Ссылка);
ДокNotification.NotificationKind = 1;

Для каждого СтрокаУМ из ДанныеВыгрузки Цикл
    // Создаем регистрационную информацию
    ДокRegister = ФабрикаXDTO.Создать(Пакет.Получить("RegisterInfoType"));
    ДокRegister.MedDevicesId = 123456789;
    
    // Создаем сведения об изделии
    ДокMedDevices = ФабрикаXDTO.Создать(Пакет.Получить("MedDevicesInfoType"));
    
    // Работа с датами через создание объектов DateInfoType
    ДатаПроизводства = ФабрикаXDTO.Создать(Пакет.Получить("DateInfoType"));
    ДатаПроизводства.Date = СтрокаУМ.ДатаВвода;
    ДокMedDevices.ManufactureDate = ДатаПроизводства;
    
    // Заполнение простых полей
    ДокMedDevices.SerialNumber = СтрокаУМ.Серия;
    ДокMedDevices.Quantity = СтрокаУМ.Количество;
    
    // Добавление объекта в список (коллекцию) родителя
    ДокRegister.MedDevicesInfo.Добавить(ДокMedDevices);
    ДокNotification.RegisterInfo.Добавить(ДокRegister);
КонецЦикла;

Важные нюансы и рекомендации

Чтобы избежать ошибок при выгрузке и последующей валидации XML на стороне сервера, обратим внимание на следующие моменты:

  1. Проверка типов данных. Если в схеме указано, что поле является числовым (например, xs:integer), передавайте именно число. Использование СериализаторXDTO.XMLСтрока() для числовых полей иногда может привести к ошибке, если принимающая сторона строго проверяет типы.
  2. Валидация объекта. Перед сохранением в файл обязательно выполните метод ДокXDTO.Проверить(). Это позволит увидеть, все ли обязательные поля заполнены. Если метод выдаст ошибку, вы поймете, какой именно вложенный объект или свойство пропущено.
  3. Настройка пространства имен. При записи XML используйте НазначениеТипаXML.Неявное. Это позволит сформировать чистый XML без избыточных атрибутов xsi:type в каждом узле, что часто является требованием СМЭВ-адаптеров.
  4. Регистр имен. В XDTO крайне важен регистр. DateInfoType и dateinfotype — это разные типы с точки зрения фабрики. Всегда копируйте имена типов и свойств непосредственно из схемы XDTO в конфигураторе.

Таким образом, ключ к решению проблемы несоответствия типов — это понимание структуры XSD-схемы. Если свойство имеет объектный тип, мы всегда должны пройти через этап создания этого объекта с помощью ФабрикаXDTO.Создать(), прежде чем наполнять его данными.

← На главную