Как передать сложный тип данных (перечисление) в веб-сервис 1С?

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

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

Проанализируем типичный пример кода, который вызывает подобную ошибку:


ТипП = wsПрокси.ФабрикаXDTO.Пакеты.Получить("http://myPacket.ru").Получить("Setting");
WSПараметр = wsПрокси.ФабрикаXDTO.Создать(ТипП);
// Попытка передать созданный объект сложного типа
ДанныеПациент = WSПрокси.PersonalData(WSПараметр);

Выясним причину такого поведения и рассмотрим рабочие способы решения этой проблемы.

Анализ проблемы: почему возникает ошибка?

Ключевая проблема кроется в контракте веб-сервиса (WSDL-описании). Если мы заглянем в определение веб-сервиса, то часто обнаружим, что ожидаемый тип данных для нашего параметра — это обычная строка: string (http://www.w3.org/2001/XMLSchema).

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

Способ 1: Передача строкового представления

Если веб-сервис ожидает строку, самым простым и логичным решением будет передать строковое представление перечисления. Давайте посмотрим, как это сделать:

Вместо создания сложного XDTO-объекта, мы можем извлечь строковый эквивалент значения перечисления в 1С или просто передать нужный текст, который ожидает принимающая сторона. А уже на стороне приемника (если это тоже 1С или другая система, логику которой мы понимаем) обрабатывать эту строку.


// Передаем строку напрямую
СтроковоеЗначение = "ИмяЗначенияПеречисления";
ДанныеПациент = WSПрокси.PersonalData(СтроковоеЗначение);

Если принимающая сторона — это тоже 1С, то там разработчик сможет легко преобразовать полученную строку обратно в перечисление:

ТекЗначение = Перечисления.ВашеПеречисление[ИмяПеречисленияИзСтроки];

Способ 2: Работа с XDTO, если сервис действительно ждет сложный тип

Если мы уверены, что сервис обязан принимать сложный тип (или мы сами можем поменять WSDL), рассмотрим подробнее технические нюансы работы с XDTO в 1С.

1. Особенности типизации перечислений

В XDTO перечисление (Enum) не является самостоятельным объектом вроде ОбъектXDTO. Как правило, оно описывается как простой тип (Simple Type), который базируется на строке с ограничениями (restriction) в виде списка допустимых значений (enumeration). Поэтому не нужно создавать отдельный объект под само перечисление. Достаточно создать родительский объект, а его свойству присвоить нужную строку из списка допустимых.

2. Использование правильной фабрики

Всегда используйте локальную фабрику прокси-объекта — wsПрокси.ФабрикаXDTO. Использование глобальной ФабрикаXDTO может привести к ошибкам совместимости типов, так как именно локальная фабрика содержит точные пространства имен (namespaces) конкретного стороннего сервиса.

3. Чувствительность к регистру

Обратите внимание на точное написание значений перечисления в XML-схеме стороннего сервиса. XML строго чувствителен к регистру. Если в WSDL написано Active, то передача ACTIVE или Активно гарантированно приведет к ошибке валидации на стороне сервера.

Способ 3: Отладка отправляемых пакетов XML

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


Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку();

// Записываем наш параметр в XML для проверки
wsПрокси.ФабрикаXDTO.ЗаписатьXML(Запись, WSПараметр);

// Выводим результат
ТекстXML = Запись.Закрыть();
Сообщить(ТекстXML);

Этот прием позволяет увидеть реальную структуру пакета. Вы сможете проверить, нет ли лишних пространств имен, правильно ли заполнены теги и присутствует ли атрибут xsi:type, если сторонний сервис требует явного указания типа данных в полиморфных запросах.

Способ 4: Сериализация объекта в строку (обходной маневр)

Бывают ситуации, когда контракт стороннего сервиса (WSDL) написан с ошибкой: параметр описан как string, но документация утверждает, что туда нужно передать XML со сложной структурой. В этом случае мы можем пойти на хитрость:

  1. Создать полноценный объект XDTO со всеми вложенными перечислениями.
  2. Сериализовать его в строку формата XML (используя код из Способа 3).
  3. Передать полученную строку как обычный строковый параметр в функцию веб-сервиса.

При таком подходе 1С корректно пропустит вызов метода (так как мы передаем строку, как и требует WSDL), а сторонний сервис получит нужную ему сложную структуру внутри этой строки.

← На главную