При интеграции платформы 1С:Предприятие 7.7 со сторонними веб-сервисами, интернет-магазинами или государственными информационными системами разработчики часто сталкиваются с необходимостью разбора файлов формата JSON. Поскольку в устаревшей платформе 1С 7.7 нет встроенных нативных средств для работы с JSON, стандартным решением является использование внешнего OLE-объекта MSScriptControl.ScriptControl для выполнения JavaScript-кода.
Однако в процессе реализации парсинга разработчики нередко сталкиваются с неприятной ошибкой: «Плохой тип переменной» при вызове метода парсинга. В этой статье мы подробно разберем, почему возникает данная ошибка, как ее оперативно исправить, а также проанализируем альтернативные и более стабильные способы работы с JSON в среде 1С 7.7.
Давайте проанализируем типичный сценарий, в котором возникает эта ошибка. Разработчик инициализирует скрипт-контроль в Глобальном модуле и пытается вызвать функцию обработки:
// Пример ошибочного вызова
РезультатРазбора = сз_FromJSON(Текст);
Внутри функции разбора выполняется обращение к COM-объекту:
obj = JSON_ctrl.run("parseJSON", стр); // Здесь падает с ошибкой "Плохой тип переменной"
Выясним причину такого поведения системы. В данном случае переменная Текст представляет собой не текстовую строку с JSON-содержимым, а специализированный объект 1С 7.7, созданный с помощью конструктора СоздатьОбъект("Текст"). Объект Текст предназначен для работы с файлами на диске (открытие, сохранение, построчный обход), но он является внутренним объектом платформы 1С.
Компонента MSScriptControl.ScriptControl — это внешняя библиотека Microsoft Windows, которая общается с 1С на уровне универсальных типов данных (строка, число, дата, булево). Она совершенно ничего не знает о внутреннем устройстве объекта Текст платформы 1С. Когда мы пытаемся передать этот объект в метод run() скрипт-контроля, OLE-интерфейс выдает ошибку несоответствия типов.
Для устранения ошибки нам необходимо предварительно прочитать содержимое файла из объекта Текст в обычную переменную строкового типа 1С. Рассмотрим, как это сделать правильно:
// 1. Создаем объект "Текст" и загружаем файл с диска
ТекстФайлаОбъект = СоздатьОбъект("Текст");
ТекстФайлаОбъект.Открыть(КаталогФС + ФайлФС);
// 2. Считываем содержимое в обычную строковую переменную 1С
СтрокаJSON = "";
Для Ном = 1 По ТекстФайлаОбъект.КоличествоСтрок() Цикл
СтрокаJSON = СтрокаJSON + ТекстФайлаОбъект.ПолучитьСтроку(Ном) + РазделительСтрок;
EndЦикл;
// 3. Теперь передаем в парсер именно строковое значение
РезультатРазбора = сз_FromJSON(СтрокаJSON);
Такой подход полностью решает проблему несовместимости типов переменных при передаче данных в среду JavaScript.
Решая проблему передачи типов, мы можем столкнуться со следующим ограничением платформы 1С 7.7. При передаче очень длинной строки (размером более 1–2 Мегабайт) из 1С в COM-объект MSScriptControl программа может аварийно завершить работу (вылететь без сообщений об ошибках). Это связано с механизмами выделения памяти под BSTR-строки при COM-взаимодействии.
Для стабильной работы с большими файлами JSON рекомендуется использовать один из двух обходных путей:
Eval().ADODB.Stream (который отлично поддерживает кодировку UTF-8) или Scripting.FileSystemObject, считывают файл силами операционной системы и сразу же парсят его.Посмотрим на пример реализации чтения UTF-8 файла силами JavaScript внутри скрипт-контроля:
// Добавляем функцию чтения UTF-8 файла в JS-контекст
JS_Код = "
|function parseJSONFromFile(filePath) {
| var stream = new ActiveXObject('ADODB.Stream');
| stream.Type = 2; // Текстовый режим
| stream.Charset = 'utf-8';
| stream.Open();
| stream.LoadFromFile(filePath);
| var text = stream.ReadText();
| stream.Close();
| return JSON.parse(text);
|}";
JSON_ctrl.AddCode(JS_Код);
// Вызываем чтение и разбор файла без передачи строки из 1С
Результат = JSON_ctrl.Run("parseJSONFromFile", КаталогФС + ФайлФС);
Важным нюансом является то, что библиотека MSScriptControl является устаревшей и 32-битной. В современных 64-битных версиях операционных систем Windows (Windows 10 / 11, Windows Server) она часто не зарегистрирована по умолчанию в системе. Чтобы не заниматься регистрацией сторонних библиотек на компьютерах пользователей, можно использовать стандартный системный объект htmlfile, который присутствует в любой Windows.
Объект htmlfile использует под капотом движок Internet Explorer (MSHTML) и позволяет выполнять код JavaScript. Рассмотрим пример парсинга с его помощью:
// Функция разбора JSON через объект htmlfile
Функция РазобратьJSON_HTML(СтрокаJSON)
HTML = СоздатьОбъект("htmlfile");
// Включаем поддержку современного режима рендеринга и скриптов
HTML.write("<meta http-equiv='x-ua-compatible' content='IE=9'>");
HTML.write("<script>var parsedData = " + СтрокаJSON + ";</script>");
// Получаем разобранный объект обратно в 1С
Возврат HTML.parentWindow.parsedData;
КонецФункции
Если в вашей конфигурации 1С 7.7 активно используется внешняя компонента 1С++, наиболее правильным и быстрым решением будет использование классов ООП. В сообществе разработчиков 1С 7.7 создан и успешно применяется класс КОП_JSON.ert.
Для его подключения в заголовочном файле описания классов (defcls.prm) прописывается следующее объявление:
#класс JSON = КОП_JSON.ert
#{
# Неопределенный ЧтениеJSON(Строка Стр, Число Поз = 1);
# Строка ЗаписьJSON(Неопределенный Значение, Число ПереносСтрок = 0, Строка Отступ = "");
#}
При использовании класса КОП_JSON соответствие типов данных настраивается автоматически:
{}) преобразуются в объекты типа Структура или ИндексированнаяТаблица.[]) преобразуются в стандартный СписокЗначений 1С.\n, \t, \" и другие).Преимуществом такого подхода является полная автономность от системных настроек Windows, отсутствие утечек памяти и высокая скорость работы парсера на стороне встроенного языка 1С.