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

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

1С: как передать массив с сервера на клиент

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

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

Выбор способа зависит от контекста: какой клиент используется (тонкий, веб, толстый), что лежит в массиве (примитивы, структуры, ссылки), нужно ли обратное преобразование на клиенте и насколько важна производительность при больших объёмах. Ниже разобраны рабочие варианты с кодом, ограничения платформы и типичные ошибки.

Почему массив нельзя передать напрямую

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

Тип «Массив» в этот список не входит. При попытке вернуть массив из серверной процедуры с признаком вызова сервера вы получите ошибку ещё на этапе передачи результата. То же относится к передаче массива как параметра с клиента на сервер в тонком клиенте — здесь платформа тоже откажет.

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

Способ 1. Сериализация в JSON — универсальное решение

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

На сервере массив преобразуется через ЗаписьJSON. Обратите внимание: записывать можно массивы, структуры, соответствия и примитивы. Ссылки и другие несериализуемые в JSON объекты нужно предварительно превратить в строки (например, уникальный идентификатор ссылки).

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

Функция ПолучитьДанныеJSON() Экспорт

Данные = Новый Массив;

Для Каждого Строка Из ВыборкаТоваров Цикл

Элемент = Новый Структура;

Элемент.Вставить("Номенклатура", Строка(Строка.Ссылка.УникальныйИдентификатор()));

Элемент.Вставить("Наименование", Строка.Наименование);

Элемент.Вставить("Цена", Строка.Цена);

Данные.Добавить(Элемент);

КонецЦикла;

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

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

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

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

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

На клиенте строка разбирается обратно. ЧтениеJSON восстановит массив и структуры (по умолчанию — соответствия, с параметром ПрочитатьВСоответствие = Ложь — структуры, если платформа это поддерживает в вашей версии).

&НаКлиенте

Процедура ЗагрузитьДанные(Команда)

СтрокаJSON = ПолучитьДанныеJSON();

Чтение = Новый ЧтениеJSON;

Чтение.УстановитьСтроку(СтрокаJSON);

Данные = ПрочитатьJSON(Чтение);

Чтение.Закрыть();

Для Каждого Элемент Из Данные Цикл

Сообщить(Элемент.Наименование + " — " + Элемент.Цена);

КонецЦикла;

КонецПроцедуры

bsl
Запись = Новый ЗаписьJSON;
Запись.УстановитьСтроку();
ЗаписатьJSON(Запись, МассивДанных);
СтрокаJSON = Запись.Закрыть();

Способ 2. Строка с разделителем для простых данных

Если в массиве лежат только строки или числа без сложной структуры, достаточно соединить их в одну строку на сервере и разобрать на клиенте. Это компактнее JSON и не требует механизмов чтения/записи.

&НаСервере

Функция ПолучитьСписокАртикулов()

// Массив строк

Возврат СтрСоединить(МассивАртикулов, ";");

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

&НаКлиенте

Процедура Обработать()

МассивНаКлиенте = СтрРазделить(ПолучитьСписокАртикулов(), ";");

КонецПроцедуры

Критическое ограничение: разделитель не должен встречаться внутри самих значений. Если артикул может содержать точку с запятой, разбор даст неверный результат. Для чисел и дат помните о форматах: дату лучше передавать в ISO-виде (Формат(Дата, "ДФ=гггг-ММ-дд")), иначе восстановление зависит от региональных настроек.

Способ 3. Хранилище значения и временное хранилище

ХранилищеЗначения — сериализуемый тип, его можно вернуть с сервера. На сервере массив упаковывается через Новый ХранилищеЗначения(Массив), на клиенте извлекается методом Получить(). Вариант рабочий, но у него есть накладные расходы на упаковку и ограничения по содержимому: внутри хранилища тоже должны быть сериализуемые данные.

Для больших объёмов удобнее поместить данные во временное хранилище формы: ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификаторФормы) возвращает адрес (строку), который свободно передаётся на клиент. На клиенте данные забираются через ПолучитьИзВременногоХранилища(Адрес). Так платформа сама управляет передачей, а вы не гоняете огромную строку через параметры.

&НаСервере

Функция ПодготовитьДанные()

Данные = СформироватьМассивСтруктур();

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

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

&НаКлиенте

Процедура Загрузить(Команда)

Адрес = ПодготовитьДанные();

Данные = ПолучитьИзВременногоХранилища(Адрес);

КонецПроцедуры

Способ 4. Таблица значений и данные формы

Если массив по смыслу — это набор однородных записей, часто правильнее вообще отказаться от массива в пользу таблицы значений или реквизита формы типа «ТаблицаЗначений» (в форме — «ДанныеФормыКоллекция»). Реквизиты формы платформа передаёт между клиентом и сервером автоматически — никакой ручной сериализации не требуется.

Типовой приём: на сервере заполнить таблицу значений, затем ЗначениеВРеквизитФормы(Таблица, "Товары") — и данные уже доступны на клиенте. Обратно — РеквизитФормыВЗначение. Это самый «платформенный» путь для управляемых форм, и именно его стоит предпочесть, если данные отображаются в табличной части формы.

Ограничение: таблица значений тяжелее массива по памяти и трафику. Для передачи пары десятков чисел это избыточно — здесь выигрывает JSON или строка с разделителем.

Сравнение вариантов

JSON-строка

Универсально, поддерживает вложенные структуры; требует ручной записи и чтения, ссылки нужно преобразовывать в строки.

Строка с разделителем

Просто и быстро для однотипных примитивов; ломается, если разделитель встречается в данных.

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

Подходит для больших объёмов; требует управления временем жизни и привязки к форме.

Реквизит формы (таблица)

Без ручной сериализации, идеально для табличных данных формы; избыточно для мелких массивов.

Ссылки, структуры и другие проблемные типы внутри массива

Даже если вы выбрали JSON, содержимое массива нужно подготовить. Ссылки на объекты базы в JSON сериализовать нельзя — передавайте строковое представление уникального идентификатора (Строка(Ссылка.УникальныйИдентификатор())), а на клиенте при необходимости храните его как строку или ищите ссылку отдельным серверным вызовом.

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

Картинки и двоичные данные внутри массива — отдельная история: их кодируют в Base64 (Base64Строка) перед помещением в структуру, на клиенте декодируют обратно. Это заметно увеличивает объём, поэтому для файлов лучше временное хранилище.

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

Проверка результата и производительность

После передачи проверьте три вещи: количество элементов на клиенте совпадает с серверным, типы значений соответствуют ожиданиям (особенно даты и числа), а ссылки корректно восстанавливаются по идентификаторам. Удобно временно выводить в отладку первый и последний элемент на обеих сторонах.

По производительности: сериализация в JSON — операция быстрая, но передача строки на несколько мегабайт в веб-клиенте ощутимо тормозит интерфейс. Практический порог — если данные больше нескольких сотен килобайт, переходите на временное хранилище или реквизиты формы, а ещё лучше — пересмотрите, действительно ли весь массив нужен на клиенте. Часто достаточно передать порцию данных (постранично) или только итоги.

Ещё одна рекомендация: минимизируйте число серверных вызовов. Если массив нужен вместе с другими данными, соберите всё в одну структуру, сериализуйте целиком и передайте одним вызовом — десять мелких вызовов дороже одного крупного.

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

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

Количество элементов
Норма

На клиенте столько же, сколько на сервере

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

Меньше или больше — потери при разборе

Типы значений
Норма

Числа — числа, даты — даты

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

Всё стало строками — ошибка восстановления

Ссылки
Норма

По идентификатору находится объект

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

Пустая ссылка или неверный объект

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

Можно ли передать массив с клиента на сервер?

В тонком клиенте напрямую — нет, действуют те же ограничения сериализации. Используйте зеркальные приёмы: соберите JSON-строку на клиенте и разберите на сервере, либо передавайте структуру из примитивов. В толстом клиенте обычного приложения массив передаётся напрямую.

Почему ПрочитатьJSON возвращает соответствия, а не структуры?

По умолчанию JSON-объекты читаются в соответствия. В актуальных версиях платформы у ПрочитатьJSON есть параметр ПрочитатьВСоответствие — установите Ложь, чтобы получить структуры. Учтите, что тогда ключи должны быть допустимыми идентификаторами.

Как передать массив из тысяч элементов без тормозов?

Не передавайте его целиком как параметр. Поместите данные во временное хранилище на сервере и передайте клиенту только адрес, либо используйте реквизит формы. Ещё лучше — передавайте данные порциями по мере необходимости.

Что делать, если в массиве смешанные типы?

JSON это переживёт, но на клиенте вы потеряете строгость типов. Надёжнее привести элементы к единообразным структурам с явными полями — так разбор и контроль типов на клиенте становятся предсказуемыми.

Работает ли ЗначениеВСтрокуВнутр для передачи массива?

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

Итог

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

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