Как правильно возвращать структуру через веб-сервис в 1С и почему не возникает ошибка типа

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

При разработке веб-сервисов (SOAP) на платформе 1С разработчики часто сталкиваются с неожиданным поведением: в операции веб-сервиса в качестве возвращаемого значения указывается тип Structure из стандартного пакета http://v8.1c.ru/8.1/data/core, однако фактически метод возвращает сериализованный массив или примитивное значение. При этом ни на стороне сервера, ни на стороне клиента 1С исключений не возникает. Выясним причину такого поведения платформы, проанализируем риски для внешних систем и разберем правильные способы организации контрактов веб-сервисов.

Почему веб-сервис 1С пропускает несоответствие типов

Рассмотрим ситуацию на конкретном примере. В свойствах операции веб-сервиса задекларирован возвращаемый тип Structure (пакет http://v8.1c.ru/8.1/data/core). В теле функции выполняется следующий код:


Функция ПолучитьДанные()
    МассивДанных = Новый Массив;
    МассивДанных.Добавить("Тест");
    
    Возврат СериализаторXDTO.ЗаписатьXDTO(МассивДанных);
КонецФункции

На стороне клиента 1С при получении ответа через WS-прокси код успешно отрабатывает:


ОтветXDTO = Прокси.ПолучитьДанные();
Результат = СериализаторXDTO.ПрочитатьXDTO(ОтветXDTO);
// В переменной Результат оказывается Массив, а не Структура

Проанализируем, почему вызов завершается успешно:

  1. Отсутствие валидации схемы на стороне сервера: при формировании SOAP-ответа платформа 1С не сверяет фактический тип переданного объекта с типом, заявленным в WSDL-описании операции. Платформа берет готовый ОбъектXDTO, помещает его в тело конверта и явно указывает его фактический тип в XML-атрибуте xsi:type (например, xsi:type="v8:Array").
  2. Механизм десериализации на клиенте 1С: объект СериализаторXDTO ориентируется именно на фактический XML-атрибут xsi:type в полученном документе, а не на исходный WSDL-контракт операции. Поэтому десериализация восстанавливает именно тот объект, который был отправлен сервером.

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

Риски и ограничения при интеграции со сторонними системами

Если вызывающей стороной выступает не 1С, а приложение на Java, .NET, PHP или C++, возникнут проблемы:

  1. Строгая валидация контракта сторонними клиентами: внешние платформы генерируют строгие классы сущностей на этапе чтения WSDL. Если в WSDL задекларирован тип структуры, а в ответе возвращается массив, сторонний парсер выбросит фатальную ошибку валидации схемы (Schema Validation Error) или исключение приведения типов.
  2. Специфика типа Structure из пакета core: тип Structure в пространстве имен http://v8.1c.ru/8.1/data/core представляет собой список пар с ключами и универсальными значениями Value типа anyType. Для сторонних клиентов такой тип не генерирует удобный объект с именованными полями, что сильно усложняет разработку интеграции.
  3. Невозможность прямого возврата прикладных типов: метод веб-сервиса 1С не может напрямую вернуть прикладной объект (Структура, Массив, ТаблицаЗначений). Значение обязательно должно быть приведено к ОбъектXDTO, ЗначениеXDTO или базовому типу Строка. Попытка вернуть напрямую прикладной объект вызовет ошибку несоответствия типов.

Способ 1. Создание строгого XDTO-пакета (рекомендуемый подход)

Разберем эталонный способ построения SOAP веб-сервиса. Для обеспечения самодокументируемости и жесткого контракта необходимо описать собственные типы данных в дереве метаданных.

Выполним следующие шаги:

  1. В ветке метаданных XDTO-пакеты создадим новый пакет (например, с URI пространства имен http://myshop.org/integration).
  2. Внутри пакета создадим Тип объекта (например, ОтветОперации).
  3. В тип объекта добавим необходимые свойства с указанием их типов из пространства имен XML Schema (xs:string, xs:int, xs:dateTime и др.).
  4. В операции веб-сервиса выберем созданный тип в качестве типа возвращаемого значения.
  5. В коде операции сформируем объект через фабрику XDTO:

Функция ВыполнитьЗапрос()
    ТипОтвета = ФабрикаXDTO.Тип("http://myshop.org/integration", "ОтветОперации");
    ОтветXDTO = ФабрикаXDTO.Создать(ТипОтвета);
    
    ОтветXDTO.Код = 200;
    ОтветXDTO.Сообщение = "Успешно";
    ОтветXDTO.ДатаФормирования = ТекущаяДатаСеанса();
    
    Возврат ОтветXDTO;
КонецФункции

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

Способ 2. Использование типа anyType при динамическом ответе

Если веб-сервис по своей логике должен возвращать полиморфные данные (в зависимости от входных параметров — структуру, массив или скалярное значение), нельзя декларировать конкретный тип наподобие Structure. Разберем, как оформить такую операцию корректно:

  1. В свойствах возвращаемого значения операции веб-сервиса выберем тип anyType из пространства имен http://www.w3.org/2001/XMLSchema.
  2. В теле операции сериализуем требуемое значение с помощью СериализаторXDTO:

Функция ПолучитьДинамическиеДанные(ТипЗапроса)
    Если ТипЗапроса = "Массив" Тогда
        Данные = Новый Массив;
        Данные.Добавить("Элемент 1");
    Иначе
        Данные = Новый Структура("Статус", "ОК");
    КонецЕсли;
    
    Возврат СериализаторXDTO.ЗаписатьXDTO(Данные);
КонецФункции

Указание типа anyType официально разрешает возвращать любой XML-тип в соответствии со спецификацией W3C, и сторонние валидаторы не будут считать такой ответ нарушением контракта.

Способ 3. Передача сериализованной строки (JSON)

Если жесткая схема XSD не требуется, а интеграция выполняется с веб-сайтом, мобильным приложением или микросервисом, наиболее удобным вариантом является передача форматированной строки JSON.

  1. В возвращаемом типе операции веб-сервиса укажем string (пространство имен http://www.w3.org/2001/XMLSchema).
  2. В методе сериализуем структуру данных средствами платформы:

Функция ПолучитьДанныеВФорматеJSON()
    СтруктураОтвета = Новый Структура;
    СтруктураОтвета.Вставить("Результат", Истина);
    СтруктураОтвета.Вставить("Данные", Новый Массив);
    
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, СтруктураОтвета);
    
    Возврат ЗаписьJSON.Закрыть();
КонецФункции

Сторонняя система прочитает строку и легко преобразует ее в нативные структуры языка (например, в объекты JavaScript или массивы PHP) без необходимости парсинга сложных SOAP-оберток.

Способ 4. Использование HTTP-сервисов платформы

Если вся передача данных сводится к обмену JSON-строками без использования стандартов SOAP и WS-Security, целесообразно отказаться от веб-сервисов в пользу объекта конфигурации HTTP-сервисы.

HTTP-сервисы платформы 1С работают быстрее за счет отсутствия оверхеда XML-конвертов, позволяют работать со стандартными HTTP-методами (GET, POST, PUT, DELETE) и возвращать JSON напрямую в теле ответа с заголовком Content-Type: application/json.

← На главную