В практике разработки на платформе 1С:Предприятие часто возникает задача передачи и восстановления сложных объектов данных через строковые переменные. Одним из классических способов решения этой задачи является динамическое выполнение кода. В этой статье мы подробно разберем, как получить полноценный объект типа Структура из текстовой строки с помощью встроенной функции Вычислить(), проанализируем частые синтаксические ошибки, а также рассмотрим современные, более безопасные и производительные альтернативы, соответствующие стандартам разработки фирмы «1С».
Метод Вычислить() позволяет динамически исполнить выражение, переданное в виде строки, и вернуть результат его вычисления. Для того чтобы инициализировать структуру, строка должна содержать синтаксически корректный вызов конструктора объекта.
Рассмотрим базовый пример. Предположим, у нас есть строка, в которой хранится значение для структуры. Наша задача — сформировать выражение вида Новый Структура("ИмяКлюча", Значение). Основная сложность здесь заключается в правильном экранировании кавычек внутри строки 1С.
Проанализируем пример корректного формирования строки для вычисления:
// Исходное значение, которое мы хотим поместить в структуру
ИмяКлюча = "Число";
ЗначениеКлюча = 1;
// Формируем строковый шаблон выражения.
// Обратите внимание на удвоенные кавычки внутри строки — они экранируют кавычки в результирующем выражении.
СтрокаВыражения = "Новый Структура(""" + ИмяКлюча + """, " + ЗначениеКлюча + ")";
// Выполняем вычисление
ПолученнаяСтруктура = Вычислить(СтрокаВыражения);
Давайте выясним причину частой ошибки, с которой сталкиваются разработчики при написании подобных конструкций. Ошибка компилятора «Ошибка в выражении» обычно возникает из-за неверного количества кавычек при сложении строк. Если пропустить закрывающую или экранирующую кавычку, платформа не сможет распарсить выражение.
Посмотрим на пример работы с текстовыми значениями внутри вычисляемой структуры. Если значением ключа является строка, то её саму также необходимо обернуть в кавычки внутри динамического выражения:
Ключ = "Имя";
ЗначениеСтрока = "Иван";
// Чтобы выражение внутри Вычислить() выглядело как: Новый Структура("Имя", "Иван")
// Нам нужно составить следующую строку:
СтрокаВыражения = "Новый Структура(""" + Ключ + """, """ + ЗначениеСтрока + """)";
Результат = Вычислить(СтрокаВыражения);
Метод Вычислить() отлично справляется с простыми выражениями в одну строку, однако профессиональная разработка требует учета факторов безопасности и производительности. Ниже мы подробно разберем, почему данный метод не рекомендуется использовать в современных конфигурациях.
Использование функций динамического исполнения кода (Вычислить() и Выполнить()) несет в себе **критическую угрозу информационной безопасности** — уязвимость к инъекции кода (Code Injection). Если строка, передаваемая в эти методы, формируется на основе данных, полученных из внешних источников (ввод пользователя, внешние файлы, API-запросы, HTTP-сервисы), злоумышленник может внедрить туда деструктивные системные команды.
Например, если вместо ожидаемого числа в строке окажется вызов деструктивной функции, платформа послушно выполнит её с правами текущего сеанса пользователя или даже под правами сервера 1С. Это может привести к повреждению базы данных, удалению конфигурационных файлов или утечке конфиденциальной информации.
Кроме того, динамическое вычисление выражений работает существенно медленнее компилируемого кода, так как платформе каждый раз приходится выполнять синтаксический анализ строки «на лету».
Если вам необходимо передать структуру в виде строки (например, между сервером и клиентом или в рамках интеграции) и затем восстановить её, наиболее современным и безопасным стандартом в 1С является использование формата JSON.
Этот способ полностью исключает выполнение вредоносного кода, работает на порядок быстрее и поддерживается всеми современными версиями платформы (начиная с 8.3.6).
Рассмотрим по шагам, как сериализовать структуру в строку JSON и прочитать её обратно:
// 1. Создаем исходную структуру с данными разных типов
ИсходнаяСтруктура = Новый Структура;
ИсходнаяСтруктура.Вставить("Имя", "Алексей");
ИсходнаяСтруктура.Вставить("Возраст", 30);
ИсходнаяСтруктура.Вставить("Активен", Истина);
// 2. Сериализация структуры в строку JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ИсходнаяСтруктура);
СтрокаJSON = ЗаписьJSON.Закрыть();
// На выходе мы получаем безопасную строку вида: {"Имя":"Алексей","Возраст":30,"Активен":true}
Сообщить(СтрокаJSON);
// 3. Десериализация (восстановление структуры из строки)
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
// Второй параметр "Ложь" указывает платформе, что объект JSON
// нужно прочитать именно как "Структуру" (а не как "Соответствие")
ВосстановленнаяСтруктура = ПрочитатьJSON(ЧтениеJSON, Ложь);
ЧтениеJSON.Закрыть();
// Проверим полученный результат
Если ВосстановленнаяСтруктура.Свойство("Имя") Тогда
ПоказатьПредупреждение(, "Успешно восстановлено имя: " + ВосстановленнаяСтруктура.Имя);
КонецЕсли;
Если обмен данными происходит строго внутри экосистемы 1С:Предприятие (например, передача данных между различными базами или запись структуры в текстовое хранилище конфигурации), отличным и безопасным решением станет использование стандартного XML-сериализатора.
Давайте посмотрим на пример реализации сериализации структуры в XML:
// Сериализуем структуру в XML-строку
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ЗаписатьXML(ЗаписьXML, ИсходнаяСтруктура);
СтрокаXML = ЗаписьXML.Закрыть();
// Восстанавливаем структуру из XML-строки
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(СтрокаXML);
ВосстановленнаяСтруктура = ПрочитатьXML(ЧтениеXML);
Этот подход также абсолютно безопасен, так как XML-парсер платформы 1С обрабатывает только структуру данных и физически не способен выполнить заложенный в строку исполняемый программный код.
Иногда строка поступает в нестандартном текстовом виде, например: "Код=100; Наименование=Стол; Цена=5000". Использовать в таком случае Вычислить() крайне нежелательно. Правильнее и надежнее будет написать небольшую парсинг-функцию с применением стандартных методов работы со строками.
Разберем по шагам алгоритм безопасного разбора такой строки с помощью функции СтрРазделить():
// Исходная строка данных
СтрокаДанных = "Код=100; Наименование=Офисный Стол; Цена=5000";
ВыходнаяСтруктура = Новый Структура;
// Шаг 1. Разделяем строку на отдельные пары "Ключ=Значение" по разделителю ";"
МассивПар = СтрРазделить(СтрокаДанных, ";");
Для Каждого ТекущаяПара Из МассивПар Цикл
// Шаг 2. Разделяем каждую пару на Ключ и Значение по символу "="
МассивЧастей = СтрРазделить(СокрЛП(ТекущаяПара), "=");
Если МассивЧастей.Количество() = 2 Тогда
ИмяКлюча = СокрЛП(МассивЧастей[0]);
ЗначениеСтрокой = СокрЛП(МассивЧастей[1]);
// Шаг 3. Дополнительно можно выполнить приведение типов
// Например, если строка состоит только из цифр, преобразуем её в Число
// Для этого попробуем привести тип через Число() в попытке
Попытка
ЗначениеПриведенное = Число(ЗначениеСтрокой);
Исключение
ЗначениеПриведенное = ЗначениеСтрокой;
КонецПопытки;
ВыходнаяСтруктура.Вставить(ИмяКлюча, ЗначениеПриведенное);
КонецЕсли;
КонецЦикла;
Этот алгоритм работает без риска сбоев компиляции, полностью контролируется вами как разработчиком и работает чрезвычайно быстро.
Если перед вами все же стоит жесткая задача динамического исполнения и обойтись без этого в архитектуре невозможно, важно четко понимать разницу между операторами Вычислить() и Выполнить():
Вычислить() — используется для вычисления **одного конкретного выражения**, возвращающего результат. Внутри этого метода нельзя объявлять переменные, использовать условия Если ... КонецЕсли или циклы. Он может только вернуть значение создаваемого объекта или результат функции.Выполнить() — позволяет запускать **целые блоки кода** с управляющими конструкциями (условия, циклы, создание новых переменных в контексте выполнения). Этот метод не возвращает значение напрямую. Чтобы забрать результат из Выполнить(), нужно предварительно определить переменную в текущем контексте и присвоить ей значение внутри исполняемой строки.Посмотрим на практический пример получения структуры с помощью метода Выполнить():
// Объявляем переменную в текущем контексте модуля
РезультатВыполнения = Неопределено;
// Формируем многострочный исполняемый блок кода
СтрокаКода = "РезультатВыполнения = Новый Структура;
|РезультатВыполнения.Вставить(""Код"", 123);
|РезультатВыполнения.Вставить(""Тип"", ""Товар"");";
// Выполняем полноценный блок кода
Выполнить(СтрокаКода);
// Переменная РезультатВыполнения теперь хранит готовую структуру
Сообщить(РезультатВыполнения.Тип); // Выведет "Товар"
Мы детально проанализировали особенности работы с динамическим кодом в 1С. Метод Вычислить() решает задачу быстрого преобразования строки в структуру, но требует скрупулезного контроля над синтаксисом кавычек и таит в себе серьезные уязвимости. Для долговечных и безопасных решений всегда делайте выбор в пользу современных механизмов платформы — JSON-сериализации или контролируемого парсинга строк.