Как в 1С динамически привести строку к заранее неизвестному типу данных?

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

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

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

Способ 1. Использование объекта ОписаниеТипов и метода ПривестиЗначение()

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

Если целевой тип известен в виде строки (например, "Число", "Дата", "Булево", "Строка"), мы можем инициализировать ОписаниеТипов напрямую по имени типа:


Функция ПривестиСтрокуКТипуПоИмени(ЗначениеСтрокой, ИмяТипа)
    Описание = Новый ОписаниеТипов(ИмяТипа);
    Возврат Описание.ПривестиЗначение(ЗначениеСтрокой);
КонецФункции

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


ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Значение");
ТЗ.Колонки.Добавить("Строка");
ТЗ.Колонки.Добавить("Число");
ТЗ.Колонки.Добавить("Булево");
ТЗ.Колонки.Добавить("Дата");

МассивЗначений = Новый Массив();
МассивЗначений.Добавить("1");
МассивЗначений.Добавить("Истина");
МассивЗначений.Добавить("20230101");

Для Каждого ТекЗначение Из МассивЗначений Цикл
    Стр = ТЗ.Добавить();
    Стр.Значение = ТекЗначение;
    
    Для Каждого Колонка Из ТЗ.Колонки Цикл
        КолонкаИмя = Колонка.Имя;
        Если КолонкаИмя = "Значение" Тогда 
            Продолжить; 
        КонецЕсли;
        
        Описание = Новый ОписаниеТипов(КолонкаИмя);
        Стр[КолонкаИмя] = Описание.ПривестиЗначение(ТекЗначение);
    КонецЦикла;
КонецЦикла;

Способ 2. Преобразование, когда целевой тип задан объектом Тип

Проанализируем распространенную ситуацию: разработчик получает тип из метаданных реквизита, например, через конструкцию РеквизитМетаданных.Тип.Типы()[0]. В этом случае переменная содержит значение с типом Тип, у которого отсутствует собственный метод ПривестиЗначение().

В конструктор ОписаниеТипов можно передавать не только строку с именем типа, но и массив типов или массив строк. Если у нас есть конкретный Тип, правильнее всего поместить его в массив и создать ОписаниеТипов на его основе:


Функция ПривестиСтрокуКТипу(ЗначениеСтрокой, ТребуемыйТип)
    МассивТипов = Новый Массив;
    МассивТипов.Добавить(ТребуемыйТип);
    
    Описание = Новый ОписаниеТипов(МассивТипов);
    Возврат Описание.ПривестиЗначение(ЗначениеСтрокой);
КонецФункции

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


// МетаданныеРеквизита.Тип уже содержит ОписаниеТипов
ОписаниеРеквизита = Метаданные.Документы.ПоступлениеТоваровУслуг.Реквизиты.НомерВходящегоДокумента.Тип;
ПриведенноеЗначение = ОписаниеРеквизита.ПривестиЗначение(ИсходнаяСтрока);

Особенности и скрытые нюансы метода ПривестиЗначение()

Выясним важные тонкости поведения платформы при использовании этого метода, чтобы избежать логических ошибок в коде:

  1. Отсутствие исключений при некорректном формате: Метод ПривестиЗначение() не вызывает исключений (ошибок выполнения), если входная строка повреждена или не соответствует типу. Вместо генерации исключения метод вернет дефолтное пустое значение целевого типа (для числа — 0, для даты — пустую дату '00010101000000', для булево — Ложь). Если для бизнес-логики важно отличать ошибку конвертации от реального нуля, данный метод требует дополнительной валидации строки.
  2. Правила парсинга дат: Метод корректно распознает дату в строке, если она представлена в каноническом формате "ГГГГММДД" (или "ГГГГММДДЧЧММСС"), либо строго соответствует текущим региональным настройкам информационной базы. Нестандартные форматирования дат приведут к получению пустой даты.
  3. Работа со ссылочными типами: Если целевой тип является ссылкой на справочник, документ или перечисление, метод ПривестиЗначение() из обычной строки вернет пустую ссылку этого типа. Поиск реального объекта в базе данных метод не осуществляет. Для ссылочных типов необходимо обращаться к менеджеру соответствующего объекта (через НайтиПоНаименованию(), НайтиПоКоду() или с помощью запроса).

Альтернативные подходы и их ограничения

В ходе обсуждений на форумах нередко предлагаются другие варианты, однако они имеют существенные ограничения:

  1. Конструкция Вычислить(): Позволяет исполнить строку вида Вычислить(ИмяФункцииПреобразования + "(ИсходноеЗначение)"). Данный способ категорически не рекомендуется для непроверенных входных данных, так как несет прямую угрозу безопасности (уязвимость к инъекциям кода) и жестко зависит от контекста вызова.
  2. Функция XMLЗначение(): Позволяет быстро преобразовать строку в значение заданного типа, однако ожидает строго канонический формат XML (XSD). Например, для булево поддерживаются только строки "true", "false", "1" или "0", а для даты — только стандарт ISO ("ГГГГ-ММ-ДД"). Русскоязычные строки "Истина" или привычные даты через точку вызовут аварийную остановку по ошибке разбора XML.

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

← На главную