При разработке интеграций на платформе 1С:Предприятие программисты часто сталкиваются с необходимостью передать через веб-сервис не просто строку или число, а сложные структуры данных, такие как Массив или ТаблицаЗначений. Стандартная попытка указать тип Array из пространства имен http://v8.1c.ru/8.1/data/core в определении веб-сервиса часто приводит к ошибке «Несоответствие типов» при вызове метода. Разберем подробно, почему это происходит и как правильно передавать такие данные.
Когда мы создаем веб-сервис и выбираем тип возвращаемого значения или параметра Array, платформа ожидает строго определенную структуру XML. Однако при передаче обычного объекта 1С Массив через WSПрокси, платформа не всегда может автоматически преобразовать его в нужный формат XDTO без явных указаний. Проблема усугубляется, если типы элементов внутри массива динамические или если конфигурации отправителя и получателя имеют различия в пространстве имен типов.
Для решения этой задачи мы рассмотрим наиболее эффективный способ — использование механизма XDTO-сериализации.
Самый простой и надежный способ передать массив между двумя базами 1С — это явное преобразование массива в объект XDTO перед отправкой. Для этого используется встроенный объект СериализаторXDTO. Проанализируем шаги реализации.
1. Настройка веб-сервиса
В дереве конфигурации найдем наш веб-сервис и операцию. Для параметра, который должен принимать массив, установим тип anyType (пространство имен http://www.w3.org/2001/XMLSchema). Это позволит передать объект любого типа, который 1С сможет сериализовать самостоятельно.
2. Подготовка данных на стороне клиента (отправителя)
В процедуре вызова веб-сервиса нам необходимо преобразовать программный объект Массив в формат, понятный фабрике XDTO. Рассмотрим пример кода:
&НаСервере
Процедура ВыполнитьВызовВебСервиса()
// Создаем исходный массив данных
МассивДанных = Новый Массив;
МассивДанных.Добавить("Значение 1");
МассивДанных.Добавить(100);
МассивДанных.Добавить(ТекущаяДата());
// Настраиваем соединение
Определение = Новый WSОпределения("http://server/base/ws/test?wsdl", "Логин", "Пароль");
Прокси = Новый WSПрокси(Определение, "http://www.my-ws-namespace.org", "My_Test_ws", "My_Test_wsSoap");
// Ключевой момент: используем СериализаторXDTO для преобразования
ОбъектXDTO = СериализаторXDTO.ЗаписатьXDTO(МассивДанных);
// Вызываем метод сервиса, передавая объект XDTO вместо обычного массива
Результат = Прокси.ReturnDocs(ОбъектXDTO);
КонецПроцедуры
3. Обработка данных на стороне веб-сервиса (получателя)
Внутри функции самого веб-сервиса нам нужно выполнить обратное преобразование. Если параметр в определении указан как anyType, то в коде 1С он придет уже в виде готового объекта. Однако, если требуется восстановить именно тип Массив, мы используем метод ПрочитатьXDTO.
Функция ReturnDocs(ВходнойПараметр)
// Преобразуем полученный XDTO обратно в массив 1С
Массив = СериализаторXDTO.ПрочитатьXDTO(ВходнойПараметр);
// Теперь с объектом "Массив" можно работать как обычно
Для Каждого Элемент Из Массив Цикл
// Обработка элементов
КонецЦикла;
Возврат "Данные получены";
КонецФункции
Передача ТаблицаЗначений технически мало чем отличается от передачи массива, но имеет свои нюансы. Напрямую сериализовать таблицу значений можно через тот же СериализаторXDTO, однако это создаст очень громоздкий XML-пакет, содержащий описание колонок, типов данных и индексов. Это может существенно замедлить работу при больших объемах данных.
Разберем более оптимальный алгоритм передачи таблицы:
ТаблицаЗначений в Массив Структур. Каждая структура будет представлять собой строку таблицы, где ключ — имя колонки.СериализаторXDTO.ЗаписатьXDTO().Выясним причину, почему это лучше: структуры и массивы являются универсальными типами, их легче обрабатывать, и они корректно передаются даже в том случае, если на одной стороне используется тип данных, которого нет на другой (например, специфическое перечисление).
Пример подготовки таблицы значений:
Функция ПреобразоватьТЗвМассив(ТаблицаДанных)
МассивРезультат = Новый Массив;
Для Каждого СтрокаТЗ Из ТаблицаДанных Цикл
СтруктураСтроки = Новый Структура;
Для Каждого Колонка Из ТаблицаДанных.Колонки Цикл
СтруктураСтроки.Вставить(Колонка.Имя, СтрокаТЗ[Колонка.Имя]);
КонецЦикла;
МассивРезультат.Добавить(СтруктураСтроки);
КонецЦикла;
Возврат МассивРезультат;
КонецФункции
Проанализируем современный подход, который часто используется в высоконагруженных системах. Вместо того чтобы полагаться на сложные механизмы XDTO и anyType, данные можно передавать в виде обычной строки в формате JSON.
Преимущества этого метода:
Рассмотрим, как реализовать передачу массива через JSON:
// Код на стороне отправителя
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, МойМассивИлиТЗ);
СтрокаДляПередачи = ЗаписьJSON.Закрыть();
// Передаем СтрокаДляПередачи в веб-сервис (тип параметра в WSDL - string)
Результат = Прокси.ИмяМетода(СтрокаДляПередачи);
// Код на стороне получателя (внутри веб-сервиса)
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ВходнаяСтрока);
Данные = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Рассмотрим несколько критических моментов, которые помогут избежать ошибок в будущем:
1. Ограничение типов в таблицах и массивах. Если вы используете СериализаторXDTO, убедитесь, что внутри вашего массива или таблицы нет ссылочных данных (например, СправочникСсылка или ДокументСсылка). При передаче ссылки через веб-сервис, система попытается передать объект целиком или выдаст ошибку. Лучше передавать Уникальный Идентификатор (GUID) в виде строки, а на принимающей стороне находить объект по этому идентификатору.
2. Использование собственных XDTO-пакетов. Если к вашему веб-сервису обращается не другая 1С, а внешняя система, использование anyType крайне не рекомендуется. В этом случае следует создать в конфигурации свой XDTO-пакет, описать в нем структуру объекта (например, "СписокТоваров", содержащий элементы "Товар") и использовать этот тип в веб-сервисе. Это создаст четкую структуру в WSDL-файле, которую внешние разработчики смогут легко импортировать в свои проекты.
3. Большие объемы данных. Помним, что веб-сервисы работают по протоколу HTTP и имеют ограничения на размер передаваемого XML. Если массив содержит десятки тысяч строк, рекомендуется сжимать его в ZIP-архив, переводить в Base64 и передавать как строку, либо организовать порционную (постраничную) передачу данных.
Таким образом, мы выяснили, что для успешной передачи массива в 1С через веб-сервис необходимо либо явно сериализовать его в ОбъектXDTO и использовать тип anyType, либо переходить на использование универсального формата JSON. Оба способа являются рабочими и решают проблему несоответствия типов.