Как правильно заполнять табличную часть данными из веб-сервиса и избежать ошибки «Поле объекта не обнаружено»?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Интеграция с внешними веб-сервисами (например, сервисами ВетИС/Меркурий, маркировки «Честный Знак» или логистических операторов) — частая задача при разработке на платформе 1С. При разборе сложных ответов программисты регулярно сталкиваются с ситуацией, когда часть входящих структур не содержит определенных полей либо данные не сохраняются в строки табличной части. Проанализируем типичные причины таких ошибок и разберем надежные методы их устранения.

Анализ проблемы: почему возникает ошибка обращения к свойствам

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

стр.UUIDУпаковки = ДеталиСтроки.packingList.packingForm.UUID;

Если в схеме сервиса узел packingList объявлен как необязательный, то при его отсутствии попытка прочитать вложенное свойство packingForm немедленно вызывает критическую ошибку «Поле объекта не обнаружено» или «Попытка обращения к свойству несуществующего объекта».

Ошибочной практикой является попытка проверить заполненность строки табличной части с помощью конструкции Если ЗначениеЗаполнено(стр) Тогда. Новая строка таблицы, созданная методом Остатки.Добавить(), всегда является валидной ссылкой на строку (объект СтрокаТабличнойЧасти), поэтому такое условие всегда возвращает Истина и не защищает от ошибки при обращении к свойствам входящих данных.

Способ 1. Изолированная обработка исключений для опциональных свойств

Разберем вариант, когда тип входящего объекта не позволяет заранее проверить состав полей простым методом. Если поместить всю группу присвоений в один общий блок Попытка ... Исключение, при первой же ошибке платформа прервет выполнение всего блока и пропустит остальные корректные поля. Поэтому критичные строки необходимо изолировать:


Попытка
    стр.UUIDУпаковки = ДеталиСтроки.packingList.packingForm.UUID;
Исключение
    стр.UUIDУпаковки = "";
КонецПопытки;

Попытка
    стр.ДолжностьВетВрача = СтрокаВСД.confirmedBy.post;
Исключение
    стр.ДолжностьВетВрача = "";
КонецПопытки;

Такой подход гарантирует, что отсутствие одного опционального свойства не помешает заполнению остальных реквизитов строки.

Способ 2. Универсальная функция безопасного чтения значений

Чтобы не загромождать код десятками блоков Попытка ... Исключение, создадим компактную вспомогательную функцию. Посмотрим, как реализовать безопасное извлечение значения свойства:


Функция ПолучитьЗначениеБезопасно(Объект, ИмяСвойства, ЗначениеПоУмолчанию = Неопределено)
    Попытка
        Возврат Объект[ИмяСвойства];
    Исключение
        Возврат ЗначениеПоУмолчанию;
    КонецПопытки;
КонецФункции

Используем эту функцию для последовательного спуска по иерархии объектов:


Упаковка = ПолучитьЗначениеБезопасно(ДеталиСтроки, "packingList");
Если Упаковка <> Неопределено Тогда
    ФормаУпаковки = ПолучитьЗначениеБезопасно(Упаковка, "packingForm");
    Если ФормаУпаковки <> Неопределено Тогда
        стр.UUIDУпаковки = ПолучитьЗначениеБезопасно(ФормаУпаковки, "UUID", "");
    КонецЕсли;
КонецЕсли;

Способ 3. Проверка наличия свойства в структуре и XDTO

Если ответ десериализован в коллекцию типа Структура, используем встроенный метод Свойство():


Если ДеталиСтроки.Свойство("packingList") И ДеталиСтроки.packingList <> Неопределено Тогда
    Если ДеталиСтроки.packingList.Свойство("packingForm") И ДеталиСтроки.packingList.packingForm <> Неопределено Тогда
        стр.UUIDУпаковки = ДеталиСтроки.packingList.packingForm.UUID;
    КонецЕсли;
КонецЕсли;

Если работа ведется напрямую с объектами ОбъектXDTO, состав доступных свойств проверяется через свойства типа XDTO:


Если ДеталиСтроки.ТипXDTO.Свойства.Получить("packingList") <> Неопределено 
    И ДеталиСтроки.packingList <> Неопределено Тогда
    стр.UUIDУпаковки = ДеталиСтроки.packingList.packingForm.UUID;
КонецЕсли;

Проблема незаполнения данных: проверка типов колонок табличной части

Нередко возникает ситуация, когда при отладке в окне «Вычислить выражение» значение переменной отображается корректно, однако в строке табличной части колонка остается пустой. Выясним причину этого поведения:

  1. Несоответствие типов данных: если реквизит табличной части имеет строгий тип (например, Число или ссылку на справочник), а из сервиса передается строковый GUID без преобразования, платформа 1С не сможет выполнить неявное приведение и очистит поле.
  2. Несоответствие длины строки: если реквизит имеет тип Строка(10), а записывается идентификатор длиной 36 символов, значение может обрезаться или вызывать некорректное отображение.
  3. Формат даты: строки с датами в формате ISO 8601 (например, 2023-11-20T14:30:00) требуют явного преобразования в тип Дата с помощью функций разбора XML-дат или функции XMLЗначение(Тип("Дата"), ...).

Оптимизация: исключение поиска ссылок внутри цикла

Обратим внимание на частую ошибку производительности при заполнении табличной части — многократный вызов методов поиска внутри цикла:


// Неоптимальный код: порождает отдельный запрос к СУБД на каждой итерации
стр.Продукция = Справочники.ОписаниеПродукцииВетис.НайтиПоРеквизиту("GUID", Строка(ДеталиСтроки.product.guid));

При обработке сотен строк такой код существенно замедляет работу. Разберем правильный алгоритм пакетной выборки данных:

  1. Собрать все уникальные идентификаторы (GUID) из ответа веб-сервиса в массив.
  2. Выполнить один запрос к справочнику с условием ГДЕ GUID В (&МассивИдентификаторов).
  3. Выгрузить результат запроса в объект Соответствие, где ключом будет GUID, а значением — ссылка на элемент справочника.
  4. В цикле заполнения табличной части получать готовую ссылку из соответствия по ключу за константное время: стр.Продукция = СоответствиеСсылок.Получить(КлючGUID);.

Применение безопасного чтения свойств в сочетании с корректной настройкой типов колонок и пакетными запросами обеспечивает стабильную и быструю обработку любых входящих пакетов данных из веб-сервисов.

← На главную