При разработке веб-сервисов в среде 1С программисты часто сталкиваются с необходимостью передачи сложных коллекций данных, таких как ТаблицаЗначений, внутри которой могут находиться не только примитивные типы (строки, числа), но и другие структуры. Стандартные механизмы платформы предоставляют несколько путей решения этой задачи, каждый из которых имеет свои особенности реализации и ограничения.
В этой статье мы разберем основные способы передачи табличных данных через веб-сервисы, проанализируем ошибки при работе со структурами и научимся создавать собственные типы в XDTO-пакетах для обеспечения надежного обмена данными. Если же ручное проектирование веб-сервисов кажется слишком трудоемким, для быстрого развертывания обмена табличными данными можно применить конструктор API для обмена в формате JSON.
Самый простой на первый взгляд способ — упаковать таблицу значений в ХранилищеЗначения. Этот метод позволяет передать практически любой объект 1С, который поддерживает сериализацию, в бинарном виде.
Рассмотрим пример реализации на стороне сервера:
Функция GetTV()
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Имя");
ТЗ.Колонки.Добавить("Структура");
СтрТЗ = ТЗ.Добавить();
СтрТЗ.Имя = 55;
// Внимание: ключи структуры должны соответствовать правилам именования переменных!
НоваяСтруктура = Новый Структура("Ключ111", "345");
СтрТЗ = ТЗ.Добавить();
СтрТЗ.Структура = НоваяСтруктура;
Возврат Новый ХранилищеЗначения(ТЗ, Новый СжатиеДанных(9));
КонецФункции
Важные нюансы:
ValueStorage (из пространства имен http://v8.1c.ru/8.1/data/core)."111"), платформа выдаст ошибку при попытке сериализации. Ключи структуры в XML превращаются в имена тегов, а XML-теги не могут начинаться с цифр. Всегда проверяйте, чтобы ключи соответствовали правилам именования переменных 1С.ValueStorage закрыто внутренним алгоритмом 1С.Платформа 1С имеет предопределенный тип XDTO для таблиц значений — ValueTable. Мы можем указать его напрямую в типе возвращаемого значения операции веб-сервиса. Однако здесь есть тонкость в именовании: часто разработчики ошибаются, записывая тип как "TableValue". Правильное системное наименование — ValueTable.
Проанализируем, как это работает в коде:
Функция ПолучитьДанныеТаблицей()
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Код");
ТЗ.Колонки.Добавить("Наименование");
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Код = 1;
НоваяСтрока.Наименование = "Тестовый товар";
Возврат ТЗ; // Платформа сама попытается сериализовать ТЗ в формат ValueTable
КонецФункции
Если автоматическая сериализация не срабатывает (например, из-за сложной вложенности), можно явно воспользоваться объектом СериализаторXDTO:
Возврат СериализаторXDTO.ЗаписатьXDTO(ТЗ);
Этот метод более "прозрачен" для сторонних систем, чем хранилище значений, так как структура XML будет содержать описание колонок и строк, хотя она все равно остается специфичной для экосистемы 1С.
Для создания по-настоящему универсального и строго типизированного интерфейса рекомендуется создать собственный XDTO-пакет. Это позволит вам жестко описать структуру таблицы: какие колонки в ней есть, какие типы данных они содержат и как называются элементы. Чтобы ускорить этот процесс и избежать ручного описания структуры в конфигураторе, можно использовать обработку для автоматического формирования XSD-схем.
Разберем процесс создания по шагам:
http://www.mysite.ru/exchange).Тип объекта с именем TableLine. В нем создайте свойства, соответствующие вашим колонкам (например, Name типа string, Value типа decimal).Тип объекта (например, CustomStructure) и укажите его как тип одного из свойств в TableLine.Тип объекта с именем Table, в котором создайте свойство Rows. У этого свойства установите Максимальное количество в значение -1 (неограничено) и выберите тип TableLine.Теперь рассмотрим, как программно заполнить эту структуру на сервере:
Функция GetXDTOData()
// Получаем фабрику и типы из нашего пакета
Фабрика = ФабрикаXDTO;
ТипТаблицы = Фабрика.Тип("http://www.mysite.ru/exchange", "Table");
ТипСтроки = Фабрика.Тип("http://www.mysite.ru/exchange", "TableLine");
// Создаем корневой объект таблицы
ОбъектТаблица = Фабрика.Создать(ТипТаблицы);
// Допустим, у нас есть исходная ТЗ
Для Каждого СтрокаТЗ Из ИсходнаяТЗ Цикл
НоваяСтрокаXDTO = Фабрика.Создать(ТипСтроки);
НоваяСтрокаXDTO.Name = СтрокаТЗ.Имя;
НоваяСтрокаXDTO.Value = СтрокаТЗ.ЧисловоеЗначение;
// Добавляем заполненную строку в массив строк таблицы
ОбъектТаблица.Rows.Добавить(НоваяСтрокаXDTO);
КонецЦикла;
Возврат ОбъектТаблица;
КонецФункции
Преимущества этого подхода:
Если в одной из колонок вашей таблицы данных может находиться "что угодно" (и строка, и число, и структура), вы можете использовать тип anyType (из пространства имен http://www.w3.org/2001/XMLSchema). Это самый универсальный тип в XDTO, который позволяет упаковать любой объект. Однако помните, что принимающая сторона должна быть готова к программному определению типа полученного значения.
Также не забывайте про современные альтернативы. В некоторых случаях гораздо проще преобразовать таблицу значений в строку JSON и передать её как обычный string. Это избавляет от необходимости настройки сложных XDTO-пакетов, но перекладывает задачу парсинга данных на получателя:
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ТЗ);
СтрокаJSON = ЗаписьJSON.Закрыть();
Возврат СтрокаJSON;
Выяснив причины ошибок сериализации (такие как некорректные имена ключей) и изучив возможности XDTO, вы сможете проектировать надежные и производительные веб-сервисы для любых задач интеграции.