Как разобрать JSON в структуру в 1С 8.2, если отсутствует встроенный объект ЧтениеJSON?

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

При работе со старыми релизами платформы 1С:Предприятие 8.2 (до версии 8.3.6) разработчики часто сталкиваются с серьезным ограничением: отсутствием встроенного объекта ЧтениеJSON. В современных версиях разбор строки JSON — это дело одной строки кода, но в условиях наследуемых систем нам приходится искать альтернативные пути. В этой статье мы подробно разберем, как реализовать парсинг JSON своими силами, рассмотрим несколько проверенных подходов и проанализируем потенциальные «подводные камни», которые могут привести к ошибкам в данных.

Метод 1. Использование скриптового движка JScript через COM-объект

Проанализируем самый надежный способ, который де-факто является стандартом для старых систем Windows. Суть заключается в использовании системного объекта MSScriptControl.ScriptControl. Поскольку формат JSON является подмножеством языка JavaScript, мы можем заставить движок JScript выполнить разбор строки и вернуть нам готовый объект.

Рассмотрим по шагам, как это реализовать:

  1. Создаем экземпляр MSScriptControl.ScriptControl.
  2. Устанавливаем язык JScript.
  3. Используем метод eval() для превращения строки JSON в объектную структуру JavaScript.

Этот метод хорош тем, что он корректно обрабатывает экранирование символов, кавычки внутри строк и спецсимволы, такие как \n или \t. Однако помните, что на 64-битных серверах этот COM-объект может быть недоступен напрямую, поэтому код лучше выполнять на клиенте или в 32-битной среде.

Метод 2. Рекурсивный парсер на «чистом» 1С

Если по каким-то причинам использование внешних COM-объектов невозможно (например, из-за политик безопасности или работы в среде Linux), нам придется написать функцию разбора самостоятельно. Рассмотрим алгоритм, который обходит строку и преобразует ее в объекты Структура и Массив.

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


Процедура ЗаполнитьДанныеИзОтветаJSON(Результат, ТекстJSON, ТипДанных)
    ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));	
    НомерЗначения = 0;
    
    Пока ТекстJSON <> "" Цикл
        ПервыйСимвол = Лев(ТекстJSON, 1);
        Если ПервыйСимвол = "{" Тогда
            Значение = Новый Структура;
            ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Структура");
            Если ТипДанных = "Структура" Тогда
                Результат.Вставить("Значение" + ?(НомерЗначения = 0, "", НомерЗначения), Значение);
                НомерЗначения = НомерЗначения + 1;
            Иначе
                Результат.Добавить(Значение);
            КонецЕсли;
        ИначеЕсли ПервыйСимвол = "[" Тогда
            Значение = Новый Массив;
            ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Массив");
            Если ТипДанных = "Структура" Тогда
                Результат.Вставить("Значение" + ?(НомерЗначения = 0, "", НомерЗначения), Значение);
                НомерЗначения = НомерЗначения + 1;
            Иначе
                Результат.Добавить(Значение);
            КонецЕсли;
        ИначеЕсли (ПервыйСимвол = "}" И ТипДанных = "Структура") ИЛИ (ПервыйСимвол = "]" И ТипДанных = "Массив") Тогда
            ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
            Если Лев(ТекстJSON, 1) = "," Тогда
                ТекстJSON = СокрЛП(Сред(ТекстJSON, 2));
            КонецЕсли;
            Возврат;
        Иначе
            // Обработка ключей и простых значений
            Если ТипДанных = "Структура" Тогда
                Поз = Найти(ТекстJSON, ":");
                Если Поз = 0 Тогда Прервать; КонецЕсли;
                ИмяЗначения = СокрЛП(СтрЗаменить(Лев(ТекстJSON, Поз-1), """", ""));
                ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз+1));
                
                // Рекурсивный вызов для вложенных структур
                Если Лев(ТекстJSON, 1) = "{" Тогда
                    Значение = Новый Структура;
                    ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Структура");
                ИначеЕсли Лев(ТекстJSON, 1) = "[" Тогда
                    Значение = Новый Массив;
                    ЗаполнитьДанныеИзОтветаJSON(Значение, ТекстJSON, "Массив");
                Иначе
                    // Поиск конца значения
                    Поз = 0;
                    Для Сч = 1 По СтрДлина(ТекстJSON) Цикл
                        Символ = Сред(ТекстJSON, Сч, 1);
                        Если Символ = "," ИЛИ Символ = "]" ИЛИ Символ = "}" Тогда
                            Поз = Сч; Прервать;
                        КонецЕсли;
                    КонецЦикла;
                    
                    Если Поз = 0 Тогда
                        Значение = ТекстJSON;
                        ТекстJSON = "";
                    Иначе
                        Значение = Лев(ТекстJSON, Поз-1);
                        ТекстJSON = СокрЛП(Сред(ТекстJSON, Поз + ?(Сред(ТекстJSON, Поз, 1) = ",", 1, 0)));
                    КонецЕсли;
                    Значение = СокрЛП(СтрЗаменить(Значение, """", ""));
                КонецЕсли;
                Результат.Вставить(ИмяЗначения, Значение);
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

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

Метод 3. Использование регулярных выражений (VBScript.RegExp)

Если нам нужно не просто разобрать весь JSON целиком, а быстро вытащить значения конкретных полей, мы можем использовать объект VBScript.RegExp. Это позволяет избежать написания сложных рекурсивных циклов.

Проанализируем ситуацию: нам нужно получить значение поля token из ответа сервера. Вместо полного парсинга мы задаем шаблон поиска. Это значительно быстрее и требует меньше памяти при работе с большими объемами данных. Однако для извлечения вложенных массивов этот метод становится слишком громоздким.

Метод 4. Преобразование в код 1С и функция Вычислить()

Еще один остроумный способ — это трансформация строки JSON в строку инициализации объектов 1С. Мы заменяем синтаксические элементы JSON на конструкторы 1С:

После такой подготовки мы вызываем стандартную функцию Вычислить(). Рассмотрим пример концепции:


// Это упрощенная концепция!
Стр1С = ТекстJSON;
Стр1С = СтрЗаменить(Стр1С, "{", "Новый Структура(");
Стр1С = СтрЗаменить(Стр1С, ":", ",");
Стр1С = СтрЗаменить(Стр1С, "}", ")");
// Далее используется Вычислить(Стр1С)

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

Метод 5. Использование внешних компонент и готовых библиотек

Посмотрим на примеры профессиональных решений. За годы существования платформы 8.2 сообщество создало мощные инструменты для работы с JSON. Самыми популярными являются:

  1. Библиотеки на основе Native API — они работают максимально быстро, сравнимо со встроенными средствами 8.3.
  2. Скрипты на базе GitHub проектов — существуют обработки, которые реализуют полноценный конечный автомат (State Machine) на языке 1С, учитывающий все нюансы спецификации RFC 7159.

Подведем итог. Если вы работаете на 1С 8.2, лучшим выбором будет использование MSScriptControl для Windows-окружения. Если же требуется кроссплатформенность, выбирайте проверенные библиотеки с открытым кодом, которые реализуют посимвольный разбор с учетом экранирования, вместо написания собственных простых функций «на коленке». Для быстрого разбора и интерактивного анализа структуры данных подойдёт обработка для преобразования JSON в дерево значений.

← На главную