К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как передать объект с сервера на клиент в 1С

Как передать объект с сервера на клиент в 1С: структуры, хранилище значений, сериализация в JSON, временное хранилище. Ограничения, примеры кода и типичные ошибки.

В клиент-серверной архитектуре 1С код выполняется в двух контекстах: на сервере, где доступны запросы к базе данных и объектные типы (СправочникОбъект, ДокументОбъект), и на клиенте, где работает интерфейс и запрещено большинство объектных операций. Из-за этого разделения напрямую «отдать» объект с сервера на клиент нельзя — платформа просто не сериализует прикладные объекты. Вместо этого данные упаковывают в переносимые типы или передают через форму.

Ошибка «Передача данных между клиентом и сервером невозможна» или сообщение о недопустимом типе параметра — типичный признак того, что разработчик попытался вернуть из серверной процедуры объект, который платформа не умеет сериализовать. Правильный подход зависит от того, что именно нужно передать: набор полей, таблицу значений, ссылку или результат сложной обработки.

Почему объект нельзя передать напрямую

Платформа 1С жёстко разделяет контексты исполнения. На сервере доступны объектные типы данных: СправочникОбъект, ДокументОбъект, Запрос, ПостроительОтчета и другие. На тонком и веб-клиенте эти типы недоступны в принципе — там существуют только ссылки, примитивные типы и ограниченный набор коллекций.

Когда серверная процедура возвращает значение, платформа пытается его сериализовать и передать по каналу связи. Если тип не сериализуется, возникает ошибка ещё на этапе вызова. Поэтому задача формулируется иначе: не «передать объект», а «передать данные объекта» — его реквизиты, табличные части, ссылки.

Способ 1. Структура с нужными полями

Самый частый сценарий — нужно получить на клиенте несколько реквизитов объекта. На сервере создаётся структура, в неё вручную переносятся нужные поля, и структура возвращается как результат функции.

&НаСервереБезКонтекста

Функция ДанныеКонтрагента(Ссылка)

Результат = Новый Структура;

Запрос = Новый Запрос("ВЫБРАТЬ Наименование, ИНН, КПП ИЗ Справочник.Контрагенты ГДЕ Ссылка = &Ссылка");

Запрос.УстановитьПараметр("Ссылка", Ссылка);

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

Результат.Вставить("Наименование", Выборка.Наименование);

Результат.Вставить("ИНН", Выборка.ИНН);

Результат.Вставить("КПП", Выборка.КПП);

КонецЕсли;

Возврат Результат;

КонецФункции

Обратите внимание: данные получаются запросом, а не через объект. Это быстрее, потому что не вычитываются все реквизиты и табличные части, и безопаснее для передачи. Структура, массив и соответствие свободно передаются между контекстами, если внутри них лежат только сериализуемые значения.

Способ 2. Временное хранилище для больших данных

Таблицы значений и результаты запросов напрямую не передаются. Для них используется временное хранилище: на сервере значение помещается туда через ПоместитьВоВременноеХранилище, а на клиент передаётся только адрес — строка-идентификатор.

&НаСервере

Функция ПодготовитьТаблицу()

ТЗ = Новый ТаблицаЗначений;

// ... заполнение таблицы

Возврат ПоместитьВоВременноеХранилище(ТЗ, УникальныйИдентификатор);

КонецФункции

На клиенте адрес передаётся обратно в серверный вызов, где данные извлекаются через ПолучитьИзВременногоХранилища. Важно: сам клиент не может прочитать таблицу значений из хранилища — обычно хранилище используют как «перевалочный пункт» между серверными вызовами, а на клиент уходит только адрес для последующей обработки или передачи в другую форму.

Второй параметр — УникальныйИдентификатор формы — привязывает время жизни хранилища к форме. Без него данные удалятся после завершения серверного вызова, и следующий вызов по адресу вернёт Неопределено.

Способ 3. Сериализация в JSON или XML

Если данные нужно передать не только между клиентом и сервером, но и во внешнюю систему, удобно сразу сериализовать их в JSON. Платформа предоставляет объекты ЗаписьJSON и ЧтениеJSON, а также глобальные методы работы с XDTO.

&НаСервереБезКонтекста

Функция ДанныеВJSON(Ссылка)

Запись = Новый ЗаписьJSON;

Запись.УстановитьСтроку();

Данные = Новый Структура("Наименование,ИНН", Ссылка.Наименование, Ссылка.ИНН);

ЗаписатьJSON(Запись, Данные);

Возврат Запись.Закрыть();

КонецФункции

Строка JSON передаётся на клиент без ограничений и там может быть разобрана через ЧтениеJSON. Минус подхода — двойное преобразование и потеря типов: даты превращаются в строки, ссылки — в строковые представления. Для внутренней передачи между контекстами формы структура обычно удобнее.

Способ 4. Передача через данные формы

Если объект открывается в управляемой форме, платформа выполняет передачу автоматически: объект преобразуется в ДанныеФормы и отображается на клиенте. Разработчику не нужно ничего сериализовать вручную — достаточно работать с реквизитами формы.

Для собственных данных формы действует тот же принцип: добавьте реквизит формы допустимого типа, заполните его на сервере в ПриСозданииНаСервере, и он будет доступен на клиенте. Для таблиц значений существует реквизит типа «ТаблицаЗначений», который форма умеет отображать и передавать.

Сравнение способов передачи

Структура / Массив

Подходит для небольшого набора полей. Просто и быстро, но таблицы значений внутрь не положить.

Временное хранилище

Для таблиц значений и больших данных между серверными вызовами. Требует контроля времени жизни и расходует память сервера.

JSON / XML

Универсально, подходит для обмена с внешними системами. Теряются типы, нужна двойная конвертация.

Реквизиты формы

Штатный путь для данных, которые отображаются пользователю. Работает только внутри формы.

Директивы компиляции и контекст вызова

Чтобы серверная функция могла вернуть значение на клиент, она должна быть объявлена с директивой &НаСервере или &НаСервереБезКонтекста в модуле формы, либо находиться в серверном общем модуле с установленными флагами «Сервер» и, при необходимости, «Вызов сервера».

Функции без контекста (&НаСервереБезКонтекста) предпочтительнее: они не пересылают на сервер состояние формы целиком, что заметно снижает трафик. Правило простое — если процедуре не нужны реквизиты формы, объявляйте её без контекста.

Порядок передачи данных объекта на клиент
  1. 1
    Определите, какие именно данные объекта нужны на клиенте — не передавайте лишнего
  2. 2
    На сервере получите данные запросом или через объект
  3. 3
    Упакуйте результат в Структуру или поместите таблицу во временное хранилище
  4. 4
    Верните структуру или адрес хранилища из серверной функции
  5. 5
    На клиенте проверьте результат на Неопределено и пустую структуру

Типичные ошибки и как их избежать

Первая ошибка — попытка вернуть объект целиком: Возврат Ссылка.ПолучитьОбъект(). Это гарантированно приводит к ошибке сериализации. Вторая — возврат РезультатаЗапроса или ВыборкиИзРезультатаЗапроса: эти типы живут только на сервере, результат нужно выгрузить в таблицу или обойти в цикле с заполнением структур.

Третья группа ошибок связана с временным хранилищем: забытый второй параметр с идентификатором формы приводит к преждевременной очистке данных, а помещение в хранилище при каждом вызове без очистки — к накоплению мусора в памяти сервера. Удаляйте ненужные данные через УдалитьИзВременногоХранилища.

Типичные ошибки
01
Возврат СправочникОбъект или РезультатаЗапроса из серверной функции — ошибка сериализации на этапе вызова
02
Помещение во временное хранилище без УникальныйИдентификатор формы — данные исчезают до следующего обращения
03
Передача всей таблицы значений ради двух колонок — лишний трафик и память сервера
04
Вызов серверной процедуры в цикле на клиенте — каждый вызов это отдельный сетевой обмен, нужно собирать данные одним запросом

Как проверить результат

После внедрения механизма проверьте три вещи. Во-первых, на клиенте данные присутствуют и имеют ожидаемый тип — удобно вывести структуру в сообщение или посмотреть в отладчике на клиентском контексте. Во-вторых, при повторных вызовах временное хранилище не копит данные. В-третьих, при пустом результате (объект не найден) клиент получает понятное пустое значение, а не ошибку.

Контрольные точки

Как проверить корректность передачи

Тип возвращаемого значения
Норма

Структура, Массив, строка, ссылка или адрес хранилища

Тревожный признак

Объект, РезультатЗапроса, ТаблицаЗначений в возврате функции

Повторный вызов с тем же адресом хранилища
Норма

Данные доступны, пока жива форма

Тревожный признак

ПолучитьИзВременногоХранилища возвращает Неопределено

Поведение при отсутствии данных
Норма

Возвращается пустая структура или Неопределено с обработкой на клиенте

Тревожный признак

Исключение или обращение к полям пустой выборки

Итог

Что важно запомнить

Объект с сервера на клиент в 1С не передаётся — передаются его данные. Используйте структуры для полей, временное хранилище для таблиц, реквизиты формы для отображения и JSON для обмена с внешними системами. Контролируйте время жизни хранилища и не передавайте лишнего.

Частые вопросы

Можно ли передать СправочникОбъект на клиент через ХранилищеЗначения?

Нет. ХранилищеЗначения сериализуемо, но прикладные объекты внутрь не помещаются — платформа выдаст ошибку ещё при записи. В хранилище можно положить структуры, таблицы значений, двоичные данные, но не объектные типы.

Как передать таблицу значений с сервера на клиент для показа пользователю?

Создайте в форме реквизит типа «ТаблицаЗначений» с нужными колонками и заполните его на сервере через ЗначениеВРеквизитФормы. Платформа сама передаст данные на клиент и отобразит их.

Почему адрес временного хранилища перестаёт работать?

Чаще всего данные помещены без привязки к форме и удалены после завершения серверного вызова. Передайте второй параметр — УникальныйИдентификатор формы — тогда данные будут жить, пока открыта форма.

Что быстрее: структура или JSON для передачи на клиент?

Структура — она передаётся платформой напрямую без двойного преобразования. JSON оправдан, когда строку нужно дополнительно сохранить, записать в файл или отправить во внешний сервис.

Можно ли вызвать серверную функцию из тонкого клиента без формы?

Да, если функция находится в общем модуле с флагами «Сервер» и «Вызов сервера». Модуль должен быть доступен для вызова, а возвращаемые типы — сериализуемыми.

Как передать картинку или файл с сервера на клиент?

Файл читается на сервере в двоичные данные, помещается во временное хранилище, а на клиент передаётся адрес. Дальше файл можно получить через ПолучитьФайл или отобразить картинку по адресу хранилища в элементе формы.