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