Как передать таблицу значений со сложной структурой через веб-сервис в 1С

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

При разработке веб-сервисов в среде 1С программисты часто сталкиваются с необходимостью передачи сложных коллекций данных, таких как ТаблицаЗначений, внутри которой могут находиться не только примитивные типы (строки, числа), но и другие структуры. Стандартные механизмы платформы предоставляют несколько путей решения этой задачи, каждый из которых имеет свои особенности реализации и ограничения.

В этой статье мы разберем основные способы передачи табличных данных через веб-сервисы, проанализируем ошибки при работе со структурами и научимся создавать собственные типы в XDTO-пакетах для обеспечения надежного обмена данными. Если же ручное проектирование веб-сервисов кажется слишком трудоемким, для быстрого развертывания обмена табличными данными можно применить конструктор API для обмена в формате JSON.

Способ 1. Использование ХранилищаЗначения (ValueStorage)

Самый простой на первый взгляд способ — упаковать таблицу значений в ХранилищеЗначения. Этот метод позволяет передать практически любой объект 1С, который поддерживает сериализацию, в бинарном виде.

Рассмотрим пример реализации на стороне сервера:


Функция GetTV()
    ТЗ = Новый ТаблицаЗначений;
    ТЗ.Колонки.Добавить("Имя");
    ТЗ.Колонки.Добавить("Структура");
    
    СтрТЗ = ТЗ.Добавить();
    СтрТЗ.Имя = 55;
    
    // Внимание: ключи структуры должны соответствовать правилам именования переменных!
    НоваяСтруктура = Новый Структура("Ключ111", "345"); 
    
    СтрТЗ = ТЗ.Добавить();
    СтрТЗ.Структура = НоваяСтруктура;
    
    Возврат Новый ХранилищеЗначения(ТЗ, Новый СжатиеДанных(9));
КонецФункции

Важные нюансы:

  1. В свойствах операции веб-сервиса необходимо указать тип возвращаемого значения ValueStorage (из пространства имен http://v8.1c.ru/8.1/data/core).
  2. Если в структуре, которая передается внутри таблицы, ключи начинаются с цифр (например, "111"), платформа выдаст ошибку при попытке сериализации. Ключи структуры в XML превращаются в имена тегов, а XML-теги не могут начинаться с цифр. Всегда проверяйте, чтобы ключи соответствовали правилам именования переменных 1С.
  3. Этот способ идеален для обмена между двумя базами 1С, но практически бесполезен, если потребителем сервиса является внешняя система (Java, C#, Python), так как содержимое ValueStorage закрыто внутренним алгоритмом 1С.

Способ 2. Использование встроенного типа ValueTable

Платформа 1С имеет предопределенный тип XDTO для таблиц значений — ValueTable. Мы можем указать его напрямую в типе возвращаемого значения операции веб-сервиса. Однако здесь есть тонкость в именовании: часто разработчики ошибаются, записывая тип как "TableValue". Правильное системное наименование — ValueTable.

Проанализируем, как это работает в коде:


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

Если автоматическая сериализация не срабатывает (например, из-за сложной вложенности), можно явно воспользоваться объектом СериализаторXDTO:

Возврат СериализаторXDTO.ЗаписатьXDTO(ТЗ);

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

Способ 3. Создание собственного XDTO-пакета (Лучшая практика)

Для создания по-настоящему универсального и строго типизированного интерфейса рекомендуется создать собственный XDTO-пакет. Это позволит вам жестко описать структуру таблицы: какие колонки в ней есть, какие типы данных они содержат и как называются элементы. Чтобы ускорить этот процесс и избежать ручного описания структуры в конфигураторе, можно использовать обработку для автоматического формирования XSD-схем.

Разберем процесс создания по шагам:

  1. Создайте в конфигурации новый XDTO-пакет (например, с URI http://www.mysite.ru/exchange).
  2. Добавьте в пакет Тип объекта с именем TableLine. В нем создайте свойства, соответствующие вашим колонкам (например, Name типа string, Value типа decimal).
  3. Если вам нужно передать структуру, создайте еще один Тип объекта (например, CustomStructure) и укажите его как тип одного из свойств в TableLine.
  4. Добавьте Тип объекта с именем 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, вы сможете проектировать надежные и производительные веб-сервисы для любых задач интеграции.

← На главную