Как преобразовать строку с вложенными скобками в массив 1С

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

В практике разработчика 1С часто встречается задача разбора текстовых данных, представленных во внутреннем формате платформы (так называемый «скобкофайл» или V8 File Format). Это могут быть файлы конфигурации, выгрузки настроек, логи замера производительности или просто текстовые строки вида "{0,{1,2}}". Наша цель — превратить такую строку в полноценный объект Массив, где каждый вложенный блок скобок станет вложенным массивом.

В этой статье мы подробно разберем несколько подходов: от быстрого «хака» через JSON до профессионального потокового парсинга больших файлов. Мы проанализируем преимущества каждого метода и выясним, какие подводные камни могут встретиться на пути.

Метод 1: Трансформация в JSON (Самый быстрый способ)

Если ваша строка имеет простую структуру, где данные разделены запятыми, а уровни вложенности обозначены фигурными скобками, мы можем воспользоваться тем, что синтаксис массивов в JSON практически идентичен формату 1С, за исключением самих символов скобок. В JSON используются квадратные скобки [], а в 1С — фигурные {}.

Рассмотрим по шагам процесс преобразования:

  1. Заменим все открывающие фигурные скобки на квадратные.
  2. Заменим все закрывающие фигурные скобки на квадратные.
  3. Используем стандартный объект платформы ЧтениеJSON для десериализации строки.

Посмотрим на пример программного кода, который реализует этот алгоритм:


&НаКлиенте
Процедура ПреобразоватьСтрокуВМассив(ИсходныйТекст)
    // Шаг 1: Подготовка строки
    ТекстJSON = СтрЗаменить(ИсходныйТекст, "{", "[");
    ТекстJSON = СтрЗаменить(ТекстJSON, "}", "]");
    
    // Шаг 2: Чтение данных
    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(ТекстJSON);
    
    Попытка
        Результат = ПрочитатьJSON(Чтение);
        // Теперь переменная 'Результат' содержит вложенные массивы
        СообщитьРек(Результат);
    Исключение
        Сообщить("Ошибка парсинга: возможно, в тексте есть некорректные символы или кавычки.");
    КонецПопытки;
КонецПроцедуры

Процедура СообщитьРек(М, Уровень = 0)
    Отступ = "";
    Для Сч = 1 По Уровень Цикл
        Отступ = Отступ + "  ";
    КонецЦикла;
    
    Для Каждого Элемент ИЗ М Цикл
        Если ТипЗнч(Элемент) = Тип("Массив") Тогда
            Сообщить(Отступ + "Вложенный массив:");
            СообщитьРек(Элемент, Уровень + 1);
        Иначе
            Сообщить(Отступ + Элемент);
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Важное ограничение: Этот метод отлично работает с числами и простыми строками. Однако, если внутри фигурных скобок находятся строковые данные, содержащие запятые или кавычки, обычная функция СтрЗаменить может нарушить структуру данных. Также помните, что в JSON строковые значения обязательно должны быть заключены в двойные кавычки. Если в вашем «скобкофайле» строки идут без кавычек, ПрочитатьJSON выдаст ошибку.

Метод 2: Использование системной функции ЗначениеИзСтрокиВнутр

Если исходная строка является результатом работы стандартных механизмов 1С (например, ЗначениеВСтрокуВнутр), то правильнее всего использовать обратную функцию. Внутренний формат 1С для массива всегда начинается со специфического идентификатора типа.

Проанализируем ситуацию: если ваша строка — это просто "{0,{1,2}}", она не является валидной для ЗначениеИзСтрокиВнутр. Чтобы она заработала, ее нужно обернуть в заголовок массива. Структура массива во внутреннем формате выглядит примерно так: {"#",51e7a0d2-530b-11d4-b98a-008048da30aa,{...}}, где GUID — это уникальный идентификатор типа Массив.

Этот метод считается наиболее надежным для восстановления сложных типов данных (дат, ссылок, уникальных идентификаторов), так как платформа сама управляет типизацией.

Метод 3: Ручной рекурсивный парсинг (для больших данных)

Выясним причину, по которой первые два метода могут не подойти. Если ваш текст занимает десятки или сотни мегабайт, попытка загрузить его целиком в память и выполнить СтрЗаменить может привести к аварийному завершению сеанса из-за нехватки ресурсов. В таких случаях мы рекомендуем использовать посимвольное чтение.

Разберем логику алгоритма на базе стека:

  1. Создаем основной массив и переменную «ТекущийМассив», а также стек (еще один массив) для хранения родительских объектов.
  2. Читаем строку по одному символу через ЧтениеТекста.
  3. При обнаружении {: создаем новый массив, добавляем его в «ТекущийМассив», сохраняем «ТекущийМассив» в стек и делаем новый массив текущим.
  4. При обнаружении запятой ,: если мы не внутри кавычек, значит, текущее накопленное значение (между скобкой или запятой) нужно добавить в массив.
  5. При обнаружении }: завершаем наполнение текущего массива и извлекаем из стека родительский массив, делая его текущим.

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

Метод 4: Использование функции Вычислить()

Существует еще один «хакерский» метод. Мы можем преобразовать строку "{0,{1,2}}" в исполняемый код 1С, заменив фигурные скобки на вызовы конструктора массива. Итоговая строка должна выглядеть так: "Новый Массив(0, Новый Массив(1, 2))" (в упрощенном виде, на самом деле конструктор массива в 1С не принимает список элементов напрямую, поэтому потребуется вспомогательная функция).

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

Специфика формата «Скобкофайл»

При реализации любого из методов нужно учитывать нюансы экранирования:

Если вам требуется профессиональный разбор сложных конфигурационных файлов, рекомендуем обратить внимание на наработки сообщества (например, парсеры от ZhokhovM или инструменты анализа замеров производительности от tormozit), которые реализуют полноценные конечные автоматы для разбора этого формата.

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


// Пример функции для очистки и подготовки простых данных
Функция ПреобразоватьПростуюСтроку(Знач Стр)
    Стр = СтрЗаменить(Стр, "{", "[");
    Стр = СтрЗаменить(Стр, "}", "]");
    
    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(Стр);
    Возврат ПрочитатьJSON(Чтение);
КонецФункции

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

← На главную