Разработка и Конфигурация · 11 мин
Какие типы данных можно передавать с сервера на клиент в 1С
Разбираем, какие типы данных 1С допустимо передавать между сервером и клиентом: примитивы, структуры, сериализуемые объекты, ограничения и типичные ошибки разработчиков.
При разработке управляемых форм и клиент-серверных механизмов в 1С разработчик постоянно сталкивается с вопросом: что именно можно вернуть из серверной процедуры в клиентскую. Платформа сериализует данные при передаче между контекстами, и далеко не каждый тип выдерживает этот «путь». Попытка передать неподдерживаемый тип приводит к ошибке вида «Переданный тип не может быть сериализован» или «Ошибка передачи данных между клиентом и сервером».
Ключевой принцип прост: между сервером и клиентом можно передавать только те значения, которые платформа умеет преобразовывать во внутреннее представление и восстанавливать на другой стороне. Это примитивные типы, коллекции из них, ссылки на объекты базы данных и ряд специальных сериализуемых типов. Объектные типы — ДокументОбъект, СправочникОбъект, запросы, построители отчётов — живут только на сервере и передаче не подлежат.
Ниже разобраны конкретные категории типов, правила их передачи, ограничения тонкого и веб-клиента, а также практические приёмы, которые позволяют обойти ограничения без потери производительности и без риска для данных.
Примитивные типы и ссылки: базовый минимум передачи
Без ограничений между контекстами передаются примитивные типы: Строка, Число, Дата, Булево, Неопределено, Null. Они сериализуются напрямую и не создают накладных расходов, кроме объёма самих данных. Именно на них строится большинство обменов «клиент вызвал сервер — сервер вернул результат».
Ссылки на объекты базы данных — СправочникСсылка, ДокументСсылка, ПеречислениеСсылка, ПланСчетовСсылка и другие — также передаются свободно. Важно понимать: передаётся только ссылка (по сути, идентификатор и тип), а не данные объекта. Обращение к реквизитам ссылки на клиенте заставит платформу выполнять неявные серверные вызовы, что при массовом обходе превращается в проблему производительности.
К этой же группе относятся УникальныйИдентификатор, Тип, ОписаниеТипов, СтандартнаяДатаНачала, Граница, МоментВремени, КлючЗаписи регистров. Все они корректно переживают сериализацию и восстанавливаются на клиенте без потерь.
Коллекции: структуры, массивы, соответствия, списки значений
Структура — основной «контейнер» для возврата составных результатов с сервера. Она сериализуется, если все её значения в свою очередь сериализуемы. Типичный приём: серверная функция собирает нужные реквизиты объекта в структуру и возвращает её клиенту, избавляя клиент от обращений к базе.
Массив и Соответствие ведут себя аналогично: передаются, если сериализуемы все элементы. Вложенность допускается — массив структур, структура с массивами внутри. СписокЗначений тоже передаётся, при этом сохраняются представления и пометки элементов, что удобно для заполнения выпадающих списков и флажков на форме.
Фиксированные варианты коллекций (ФиксированнаяСтруктура, ФиксированныйМассив, ФиксированноеСоответствие) также сериализуемы. На практике их чаще используют для параметров форм и кэширования, но как результат серверного вызова они работают так же корректно.
&НаСервереБезКонтекста
Функция ПолучитьДанныеНоменклатуры(Ссылка)
Результат = Новый Структура;
Результат.Вставить("Наименование", Ссылка.Наименование);
Результат.Вставить("Артикул", Ссылка.Артикул);
Результат.Вставить("Цены", Новый Массив);
Возврат Результат;
КонецФункцииТаблицы значений, деревья и данные формы
ТаблицаЗначений и ДеревоЗначений сериализуемы и могут быть возвращены с сервера на клиент. Это удобно для пакетной передачи наборов данных. Однако есть нюанс: на тонком и веб-клиенте прямая работа с ТаблицаЗначений ограничена — её нельзя напрямую привязать к элементу формы. Стандартный путь в управляемых формах — использовать ДанныеФормыКоллекция (реквизит формы типа «ТаблицаЗначений») и методы Загрузить/Выгрузить.
Типичный сценарий: серверная процедура заполняет таблицу значений запросом, затем реквизит формы загружается через РеквизитФормыВЗначение/ЗначениеВРеквизитФормы. Платформа сама выполняет сериализацию данных формы при передаче на клиент — разработчику не нужно вручную передавать таблицу как возвращаемое значение.
Если таблица большая, передача целиком может быть дорогой: сериализуется каждая строка и каждая колонка. В таких случаях лучше передавать только нужную страницу данных или ограничивать состав колонок, оставляя технические поля на сервере.
Двоичные данные, картинки и временное хранилище
ДвоичныеДанные и Картинка сериализуемы, но передавать их напрямую как результат функции — плохая практика при заметном объёме: данные будут гоняться через сериализацию при каждом вызове. Правильный механизм — временное хранилище. На сервере значение помещается через ПоместитьВоВременноеХранилище, клиенту возвращается только адрес (строка), а фактические данные клиент забирает через ПолучитьИзВременногоХранилища или элемент формы делает это автоматически (например, поле картинки).
Адрес временного хранилища, привязанного к уникальному идентификатору формы, живёт, пока жива форма. Если адрес создан без привязки, данные удаляются после завершения вызова — это частая причина ошибок «значение не найдено в хранилище» при асинхронных сценариях.
Файл и потоковые типы (Поток, ЧтениеДанных) не сериализуются. Работа с файловой системой клиента выполняется через НачатьПомещениеФайлаНаСервер/НачатьПолучениеФайлаССервера с использованием расширения работы с файлами, а не через передачу объектов между контекстами.
- 1На сервере получите ДвоичныеДанные (из хранилища значения, файла на диске сервера)
- 2Вызовите ПоместитьВоВременноеХранилище с указанием УникальныйИдентификатор формы
- 3Верните клиенту адрес хранилища строкой
- 4На клиенте вызовите ПолучитьИзВременногоХранилища или привяжите адрес к элементу формы
- 5Проверьте: данные открываются на клиенте без повторных серверных вызовов
Что передавать нельзя: объектные и серверные типы
Категорически не сериализуются объектные типы данных: ДокументОбъект, СправочникОбъект, ПланВидовРасчетаОбъект, наборы записей регистров, бизнес-процессы и задачи в объектном представлении. Эти типы существуют только в серверном контексте (и в толстом клиенте в файловом режиме, где контексты совмещены). Попытка вернуть их из серверной функции на тонкий или веб-клиент даст ошибку сериализации.
Не передаются также рабочие инструменты сервера: Запрос, РезультатЗапроса, ПостроительЗапроса, ПостроительОтчета, СхемаКомпоновкиДанных (в части исполнения), КомпоновщикМакета, ТабличныйДокумент в ряде контекстов тонкого клиента, COMОбъект, WSПрокси, HTTPСоединение, ФоновоеЗадание, Менеджеры объектов (СправочникиМенеджер и т.п. как значение). Всё это — ресурсы серверного сеанса, у них нет клиентского представления.
Резюме по обходу ограничения: если нужен результат запроса — выгрузите его в таблицу значений или массив структур; если нужен объект — верните ссылку плюс структуру с требуемыми реквизитами; если нужен табличный документ — на тонком клиенте он доступен, но формировать его следует на сервере и передавать готовым.
Различия клиентов и практические проверки
Толстый клиент в файловом режиме фактически не разделяет контексты — там «передача» работает иначе, и многие ограничения не проявляются. Поэтому код, отлаженный на толстом клиенте, может падать на тонком или веб-клиенте. Проверять сериализуемость нужно именно в целевом режиме работы пользователей.
Дополнительные ограничения веб-клиента: отсутствие части типов, связанных с локальной файловой системой, и особенности работы с картинками и буфером обмена. ТаблицаЗначений на тонком клиенте доступна только как значение, полученное с сервера, — создать и заполнить её программно на клиенте нельзя.
Практический тест: если сомневаетесь в типе, напишите серверную функцию, возвращающую значение, и вызовите её из тонкого клиента. Ошибка появится сразу при вызове, а не в момент использования значения — это упрощает диагностику.
Как проверить корректность передачи
Значение возвращается без ошибок сериализации
Ошибка «тип не может быть сериализован» при вызове
Только примитивы, ссылки, коллекции из них
Внутри вложен объект, запрос или набор записей
Один вызов — один пакет данных
Десятки вызовов при обходе ссылок на клиенте
Привязан к УникальныйИдентификатор формы, данные доступны
Ошибка «значение не найдено» при получении данных
Как выбрать способ передачи под задачу
Для одиночных значений и небольших наборов реквизитов достаточно структуры — это самый дешёвый и читаемый вариант. Для списков с одинаковым набором полей логичнее таблица значений или массив структур: таблица удобнее для загрузки в реквизит формы, массив — для программной обработки.
Для файлов, изображений и больших текстов — только временное хранилище. Для данных, которые нужны форме постоянно, предпочтительнее реквизиты формы: платформа сама управляет их сериализацией и обновлением представления, а разработчик избегает ручной передачи.
Как выбрать способ передачи
Что важно запомнить
Сериализуемы примитивы, ссылки, коллекции из сериализуемых значений, таблицы и деревья значений, двоичные данные и картинки. Объекты, запросы и серверные инструменты не передаются — их заменяют ссылками, структурами и выгрузками. Большие данные передают через временное хранилище, а корректность проверяют на тонком или веб-клиенте, а не на толстом.
Частые вопросы
Можно ли передать ДокументОбъект на клиент, изменить и вернуть обратно?
Нет, объектные типы не сериализуются. Правильный сценарий: на клиент передают структуру с данными, пользователь редактирует её, затем структура отправляется на сервер, где серверный код открывает объект, переносит изменения и записывает. Так сохраняется контроль транзакций и блокировок на сервере.
Почему ссылка передаётся, а обращение к её реквизиту на клиенте тормозит?
Передаётся только идентификатор ссылки. Когда код на клиенте читает реквизит, платформа выполняет скрытый серверный вызов за данными. В цикле это даёт по вызову на каждую строку. Решение — получить все нужные реквизиты одним запросом на сервере и вернуть их коллекцией.
Передаётся ли ТабличныйДокумент на тонкий клиент?
Табличный документ доступен на тонком клиенте, но формировать его следует на сервере: макеты, запросы и построители отчётов живут только там. Готовый табличный документ можно поместить в реквизит формы или вернуть как результат серверной процедуры.
Чем структура лучше таблицы значений для возврата данных?
Структура легче и понятнее для фиксированного набора полей, её дешевле сериализовать и удобнее читать в коде. Таблица значений оправдана, когда данные однотипные, многострочные и их нужно загрузить в таблицу формы или обработать методами коллекций (Найти, Свернуть, Сортировать).
Как передать на клиент результат COM- или HTTP-вызова, выполненного на сервере?
Сам COMОбъект или HTTPСоединение передать нельзя. На сервере извлеките из ответа данные — строку, число, таблицу, двоичные данные — и верните их в сериализуемом виде. Для больших ответов используйте временное хранилище.
Работает ли передача типов одинаково в файловом и клиент-серверном режимах?
Правила сериализуемости типов одинаковы, но в файловом режиме на толстом клиенте контексты совмещены, и ограничения могут не проявляться. В клиент-серверном режиме и на тонком/веб-клиенте разделение строгое. Тестировать передачу данных нужно в том режиме, в котором работают пользователи.