Как исправить ошибки сравнения типов и обращения к метаданным в HTTP-сервисах 1С

Программист 1С v8.3 (Обычные формы) 1С:Зарплата и Управление Персоналом
← На главную

При разработке интеграционных решений, таких как HTTP-сервисы, программисты часто сталкиваются с ситуациями, когда данные, полученные из запросов к базе данных, ведут себя непредсказуемо. Особенно это актуально для конфигураций, работающих в режиме совместимости (например, ЗУП 2.5 на платформе 8.3), где пересекаются старые методы работы и новые механизмы платформы. В данной статье мы разберем, как устранить ошибки сравнения несовпадающих примитивных типов и что делать, если система сообщает: «Значение не является значением объектного типа (Метаданные)».

Причина ошибки сравнения на больше-меньше

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


// Ошибка возникает здесь
Если Выборка.ДатаПриемаНаРаботу > ДатаЗапроса Тогда
    Продолжить;
КонецЕсли;

Выясним причину этой ошибки. В языке запросов 1С, если в тексте используется ЛЕВОЕ СОЕДИНЕНИЕ, и для записи из левой таблицы не найдено соответствия в правой, поля правой таблицы принимают значение NULL. Тип NULL не является датой, числом или строкой. Попытка сравнить NULL с объектом типа Дата (в нашем случае ДатаЗапроса) приводит к аварийному завершению работы кода, так как платформа не может сопоставить эти типы.

Способ 1: Проверка на NULL в программном коде

Самый быстрый способ исправить ситуацию непосредственно в цикле обхода выборки — добавить явную проверку на заполненность поля. Мы должны убедиться, что значение не является NULL, прежде чем выполнять сравнение. Перепишем условие следующим образом:


Пока Выборка.Следующий() Цикл
    // Добавляем проверку на NULL
    Если Выборка.ДатаПриемаНаРаботу <> NULL И Выборка.ДатаПриемаНаРаботу > ДатаЗапроса Тогда
        Продолжить;
    КонецЕсли;
    
    // Дальнейшая обработка данных
КонецЦикла;

Важный момент: в 1С операция сравнения <> NULL позволяет отсечь пустые значения, пришедшие из соединений таблиц, и предотвратить ошибку несовпадения типов.

Способ 2: Обработка NULL в тексте запроса (Оптимальный)

Как справедливо замечают опытные разработчики, в целях повышения производительности лучше переносить условия фильтрации в сам запрос, а не обрабатывать их в цикле. Если мы не хотим получать NULL в выборке, воспользуемся функцией ЕСТЬNULL в тексте запроса. Это позволит нам сразу назначить «пустую» дату или другое значение по умолчанию.

Разберем пример корректировки текста запроса:


Запрос.Текст = "
|ВЫБРАТЬ
|    СотрудникиОрганизаций.Ссылка КАК Сотрудник,
|    ЕСТЬNULL(СотрудникиОрганизаций.ДатаПриемаНаРаботу, ДАТАВРЕМЯ(1, 1, 1)) КАК ДатаПриема
|ИЗ
|    Справочник.СотрудникиОрганизаций КАК СотрудникиОрганизаций
|ГДЕ
|    СотрудникиОрганизаций.ДатаПриемаНаРаботу <= &ДатаЗапроса";

Используя конструкцию ГДЕ в запросе, мы существенно сокращаем объем данных, передаваемых из базы в оперативную память сервера. Это критически важно при работе с HTTP-сервисами, где скорость ответа является ключевым показателем.

Решение проблемы с метаданными и перечислениями

Вторая распространенная ошибка — Значение не является значением объектного типа (Метаданные). Чаще всего она встречается в самописных функциях получения имени перечисления, например:


Функция обИмяПеречисления(Ссылка) Экспорт
    ИмяПеречисления = Ссылка.Метаданные().Имя; // Здесь происходит ошибка
    Индекс = Перечисления[ИмяПеречисления].Индекс(Ссылка);
    Возврат Метаданные.Перечисления[ИмяПеречисления].ЗначенияПеречисления[Индекс].Имя;
КонецФункции

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

Чтобы избежать этой ошибки, выполним два шага:

  1. Проверка входного параметра: Всегда проверяйте, заполнена ли ссылка. Используйте ЗначениеЗаполнено(Ссылка).
  2. Использование XMLСтрока: Для получения внутреннего имени значения перечисления в 1С существует гораздо более эффективный и быстрый метод — XMLСтрока(). Он работает со ссылками напрямую и возвращает строковое имя значения (например, "ОсновноеМестоРаботы") без обращения к метаданным.

Посмотрим на улучшенный вариант функции:


Функция обИмяПеречисления(Ссылка) Экспорт
    Если Не ЗначениеЗаполнено(Ссылка) Тогда
        Возврат "";
    КонецЕсли;
    
    // Метод XMLСтрока для перечислений возвращает Имя значения в конфигураторе
    Возврат XMLСтрока(Ссылка);
КонецФункции

Рекомендации по работе с JSON в HTTP-сервисах

При формировании ответа в формате JSON важно помнить о типах данных. Поля структуры, которая затем сериализуется в JSON, должны содержать только примитивные типы (Строка, Число, Булево, Дата). Ссылки (СправочникСсылка, ПеречислениеСсылка) и значения NULL должны быть преобразованы заранее.

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

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


СтруктураДанных = Новый Структура;
СтруктураДанных.Вставить("Guid", Строка(Выборка.Сотрудник.УникальныйИдентификатор()));
СтруктураДанных.Вставить("Name", Выборка.ФИО);
// Обрабатываем NULL для строковых полей
СтруктураДанных.Вставить("Position", ?(Выборка.Должность = NULL, "", Строка(Выборка.Должность)));

Следуя этим правилам, мы не только избавимся от ошибок выполнения кода, но и сделаем наш HTTP-сервис более стабильным и производительным. Помните, что аккуратная обработка типов данных — залог отсутствия «необъяснимых» падений системы при изменении данных в базе.

← На главную