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

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

Как передать структуру в 1С: практическое руководство с примерами

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

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

Структура передаётся по ссылке внутри одного контекста выполнения, но копируется (сериализуется) при переходе границы клиент–сервер, при записи в хранилище и при передаче во внешние механизмы. Отсюда следуют все ограничения: внутри структуры могут находиться только те типы, которые допустимы в конкретном канале передачи.

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

Как устроена структура и почему это важно при передаче

Структура создаётся конструктором Новый Структура("Ключ1,Ключ2", Значение1, Значение2) или пустой с последующим добавлением через Вставить. Ключи — строки, допустимые как идентификаторы; значения — произвольные типы. Именно «произвольные типы» и становятся источником проблем при передаче: пока структура живёт в одном контексте, ограничений нет, но как только она пересекает границу контекста, платформа проверяет, умеет ли она упаковать каждое значение.

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

Передача структуры между процедурами и функциями

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

Процедура СформироватьДокумент(ПараметрыДокумента) Экспорт

Если Не ПараметрыДокумента.Свойство("Организация") Тогда

ВызватьИсключение "Не передана организация";

КонецЕсли;

// работа с параметрами

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

// Вызов:

Параметры = Новый Структура;

Параметры.Вставить("Организация", Организация);

Параметры.Вставить("ДатаНачала", НачалоМесяца(ТекущаяДатаСеанса()));

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

Хорошая практика — в начале вызываемой процедуры проверять наличие обязательных ключей через Свойство() и явно сообщать об ошибке. Это избавляет от трудноотлаживаемых сбоев «Поле объекта не обнаружено» в глубине алгоритма.

Если структура собирается в одном месте, а используется в нескольких, зафиксируйте состав ключей в комментарии к функции-конструктору. Разнобой в именах ключей — самая частая причина того, что переданный параметр «не виден» получателю.

Порядок действий
  1. 1
    Создайте структуру через Новый Структура или Вставить
  2. 2
    Передайте её параметром в процедуру или функцию
  3. 3
    В вызванном коде проверьте обязательные ключи через Свойство()
  4. 4
    Проверьте результат: изменения структуры видны в вызывающем коде

Передача структуры между клиентом и сервером

При вызове серверной процедуры из клиентского кода (директивы &НаСервере, &НаСервереБезКонтекста, серверные методы общих модулей) структура сериализуется на клиенте и восстанавливается на сервере. Это значит, что передаётся копия, а не ссылка: изменения структуры на сервере не вернутся на клиент автоматически, если процедура не возвращает её обратно.

Чтобы получить изменённую структуру обратно, либо верните её как результат функции, либо используйте параметр с признаком Знач по противоположной логике — на практике проще вернуть результат функцией:

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

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

Результат = Новый Структура("Успешно, Сообщение", Ложь, "");

// ... заполнение Результат

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

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

Ограничение сериализации: внутри структуры не должно быть несериализуемых типов — например, объектов типа ДокументОбъект, ТабличныйДокумент в ряде контекстов, Запрос, COMОбъект. Ссылки (ДокументСсылка, СправочникСсылка) передаются нормально. Если нужно передать таблицу значений с клиента на сервер в управляемой форме, её предварительно помещают во временное хранилище или преобразуют в массив структур.

Передача структуры в форму и обратно

Открыть форму с параметрами можно, передав структуру вторым параметром метода ОткрытьФорму. Внутри формы эти значения доступны через свойство Параметры в обработчике ПриСозданииНаСервере:

ПараметрыФормы = Новый Структура;

ПараметрыФормы.Вставить("Организация", ТекОрганизация);

ПараметрыФормы.Вставить("РежимВыбора", Истина);

ОткрытьФорму("Обработка.ПодборНоменклатуры.Форма.ФормаПодбора", ПараметрыФормы, ЭтотОбъект);

Для возврата данных из формы используется Закрыть(СтруктураРезультата) — переданная структура попадёт в обработчик ОбработкаВыбора или в описание оповещения, если форма открывалась асинхронно через ОписаниеОповещения. В модальном и асинхронном режимах механика одинаковая: формируете структуру результата и закрываете форму с ней.

Учтите: параметры формы, не объявленные в её свойствах как «Ключевые параметры», влияют на уникальность открытия. Если дважды открыть форму с одинаковым набором ключевых параметров, откроется одно и то же окно. Это и баг, и фича — в зависимости от того, что вам нужно.

Передача структуры в фоновое задание

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

ПараметрыПроцедуры = Новый Массив;

ПараметрыПроцедуры.Добавить(Новый Структура("Организация, Период", Организация, Период));

ФоновыеЗадания.Выполнить("МойМодуль.ВыполнитьОбработку", ПараметрыПроцедуры, , "Обработка данных");

Результат фонового задания структурой напрямую не возвращается. Стандартный подход — внутри фоновой процедуры поместить структуру результата во временное хранилище (ПоместитьВоВременноеХранилище) и передать адрес хранилища через параметры или получить его из механизма длительных операций. Клиент затем забирает результат по адресу.

Передача структуры через хранилище значений и JSON

Если структуру нужно сохранить в базу (например, настройки пользователя в константе или реквизите справочника типа «ХранилищеЗначения»), используйте Новый ХранилищеЗначения(Структура). При чтении — метод Получить(). Ограничения те же: все вложенные значения должны быть сериализуемыми. Дополнительно помните, что ссылки, сохранённые в хранилище, при удалении объектов из базы станут «битыми».

Для обмена с внешними системами структуру преобразуют в JSON штатными средствами: ЗаписьJSON / ЧтениеJSON с параметром ПрочитатьВСоответствие. Это удобно для HTTP-сервисов, веб-хуков и интеграций. Обратная сторона — JSON не знает типов 1С: даты, ссылки и двоичные данные придётся преобразовывать вручную (например, даты — в строки ISO).

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

Параметр процедуры

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

Клиент–сервер

Структура копируется; только сериализуемые типы; результат возвращайте функцией

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

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

JSON

Для внешних систем; требует ручного преобразования дат, ссылок и двоичных данных

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

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

Программно проверяйте обязательные ключи через Свойство("ИмяКлюча", НайденноеЗначение) — второй параметр вернёт значение, если ключ есть. Для диагностики состава удобно перебрать структуру циклом Для Каждого КлючИЗначение Из Структура Цикл и вывести ключи и типы значений в журнал регистрации или сообщения.

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

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

Состав ключей в вызванной процедуре
Норма

Все ожидаемые ключи присутствуют, типы значений совпадают с отправленными

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

Ключ отсутствует или значение изменило тип — ищите ошибку в имени ключа или несериализуемый тип

Изменения структуры после вызова
Норма

Внутри одного контекста изменения видны вызывающему коду

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

После вызова сервера изменений нет — это норма, возвращайте результат функцией

Чтение из хранилища значений
Норма

Получить() возвращает структуру с исходным составом

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

Возвращается Неопределено или ошибка — проверьте, что записывали именно ХранилищеЗначения

Типичные ошибки при передаче структур

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

Типичные ошибки
01
Ожидание, что изменения структуры на сервере вернутся на клиент — сервер получает копию, результат нужно возвращать явно
02
Передача ДокументОбъект или ТаблицаЗначений внутри структуры на сервер — ошибка сериализации; передавайте ссылку или массив структур
03
Опечатка в имени ключа при записи и чтении — Свойство() возвращает Ложь, а обращение через точку падает с ошибкой
04
Сохранение структуры со ссылками в хранилище значений без учёта удаления объектов — позже получаете битые ссылки
05
Передача структуры с реквизитом формы типа ДанныеФормыКоллекция напрямую — сначала выгрузите в таблицу значений или массив структур

FAQ

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

Да, вложенность не ограничена. Главное, чтобы на любом уровне вложенности не оказалось несериализуемых типов, если структура пересекает границу клиент–сервер, фонового задания или хранилища значений.

Чем структура отличается от соответствия при передаче?

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

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

Напрямую — только внутри одного контекста. Для передачи между клиентом и сервером преобразуйте таблицу в массив структур (каждая строка — структура) либо поместите таблицу во временное хранилище и передайте адрес.

Изменится ли исходная структура, если её изменить в вызванной процедуре?

Внутри одного контекста — да, структура передаётся по ссылке. При вызове сервера с клиента — нет, сервер работает с копией. Если нужна независимая копия внутри одного контекста, используйте метод Скопировать().

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

Напрямую структуру передать нельзя — сериализуйте её в JSON-строку и передайте как строковый параметр, а на приёмной стороне восстановите через ЧтениеJSON.

Почему ОткрытьФорму с моей структурой параметров открывает уже открытое окно?

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

Итог

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

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