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