Работа с современными форматами обмена данными, такими как JSON, в среде 1С:Предприятие 7.7 всегда сопряжена с определенными трудностями. Платформа создавалась в эпоху доминирования XML и текстовых файлов фиксированной длины, поэтому встроенных средств для парсинга JSON в ней нет. Когда объем данных достигает значительных размеров (например, 10–12 МБ), стандартные подходы через MSScriptControl начинают вызывать падение системы или работают неприемлемо долго. В этой статье мы подробно разберем, как эффективно решить задачу загрузки «тяжелых» JSON-файлов, избежав утечек памяти и обеспечив высокую скорость обработки.
Рассмотрим ситуацию, когда при попытке передать большую строку в объект MSScriptControl.ScriptControl платформа 1С 7.7 просто закрывается без объяснения причин. Это происходит из-за ограничений на передачу данных через COM-интерфейс и особенностей выделения памяти под строки в движке JScript. Проанализируем типичный ошибочный сценарий: программист считывает файл в переменную 1С, а затем пытается выполнить ScriptControl.Eval(СтрокаСДанными). При объеме в 10 МБ строка дублируется в памяти несколько раз, что приводит к критической ошибке.
Чтобы избежать этой ситуации, мы применим стратегию «чтения внутри скрипта». Вместо того чтобы передавать мегабайты текста из 1С в ScriptControl, мы передадим только путь к файлу, а чтение и парсинг доверим самому объекту JScript.
Разберем по шагам реализацию этого метода:
Функция РаспарситьJSON(ПутьКФайлу)
Скрипт = СоздатьОбъект("MSScriptControl.ScriptControl");
Скрипт.Language = "JScript";
// Добавляем вспомогательный код на JavaScript
ТекстСкрипта = "
|function parseJSONFile(path) {
| var fso = new ActiveXObject('Scripting.FileSystemObject');
| var ts = fso.OpenTextFile(path, 1);
| var str = ts.ReadAll();
| ts.Close();
| // Используем JSON.parse вместо eval для безопасности и скорости
| // Если JSON.parse недоступен (старая ОС), используем eval
| try {
| return JSON.parse(str);
| } catch(e) {
| return eval('(' + str + ')');
| }
|}";
Скрипт.AddCode(ТекстСкрипта);
ОбъектJSON = Скрипт.Run("parseJSONFile", ПутьКФайлу);
Возврат ОбъектJSON;
КонецФункции
Этот подход значительно стабильнее, так как 1С 7.7 выступает лишь в роли координатора, не перегоняя через свои внутренние буферы огромные строковые значения.
Большинство JSON-файлов приходят в кодировке UTF-8. 1С 7.7 работает с кодировкой Windows-1251. Если просто прочитать файл, вместо русских букв мы получим нечитаемые символы («кракозябры»). Рассмотрим, как можно решить эту проблему.
Самый простой, но медленный способ — посимвольный перебор строки на языке 1С. Рассмотрим этот алгоритм для понимания логики процесса:
Функция ПреобразоватьИзУТФ8(Стр)
Длина = СтрДлина(Стр);
Итог = "";
Н = 1;
Пока Н <= Длина Цикл
Знак = Сред(Стр, Н, 1);
Код = КодСимв(Знак);
Если Код < 128 Тогда
Итог = Итог + Знак;
ИначеЕсли Код >= 192 Тогда
Н = Н + 1;
Знак2 = Сред(Стр, Н, 1);
Код2 = КодСимв(Знак2);
Если Код = 208 Тогда
Если Код2 = 129 Тогда Итог = Итог + "Ё";
Иначе Итог = Итог + Симв(КодСимв("А") + Код2 - 144);
КонецЕсли;
ИначеЕсли Код = 209 Тогда
Если Код2 = 145 Тогда Итог = Итог + "ё";
Иначе Итог = Итог + Симв(КодСимв("р") + Код2 - 128);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Н = Н + 1;
КонецЦикла;
Возврат Итог;
КонецФункции
Важное замечание: Для файлов размером в 11 МБ такой перебор будет работать крайне долго (десятки минут). Проанализируем более производительный вариант с использованием объекта ADODB.Stream, который выполняет перекодировку на уровне системных библиотек мгновенно:
Функция ПрочитатьФайлВ1251(Путь)
Stream = СоздатьОбъект("ADODB.Stream");
Stream.Type = 2; // Text
Stream.Charset = "utf-8";
Stream.Open();
Stream.LoadFromFile(Путь);
Текст = Stream.ReadText();
Stream.Close();
Возврат Текст;
КонецФункции
Если файл успешно прочитан и распарсен в объект JScript, перед нами встает задача — как вытащить из него данные в 1С? Обращение к свойствам объекта через точку Объект.Property работает, но если в файле тысячи элементов, это будет медленно.
Рассмотрим альтернативное решение — использование внешней компоненты 1sqlite. Она позволяет загрузить JSON во временную базу данных SQLite прямо в памяти и работать с ним с помощью SQL-запросов. Это «термоядерный» по скорости метод. Выясним, как это реализовать:
1sqlite.dll.:memory:).Посмотрим на пример SQL-запроса, который выберет данные из вложенного массива JSON:
SELECT
json_extract(value, '$.id') as ID,
json_extract(value, '$.title') as Title
FROM json_each(?)
Здесь json_each — это функция, которая разворачивает массив JSON в плоскую таблицу. Скорость обработки файла в 11 МБ при таком подходе составит секунды, а не десятки минут.
Подведем итог и выберем оптимальный инструмент в зависимости от условий задачи:
MSScriptControl с чтением файла через FileSystemObject. Это избавит от падений по памяти, но скорость обработки будет средней.ADODB.Stream для предварительной конвертации файла в Windows-1251 перед парсингом.Используя приведенные выше методы, мы сможем эффективно интегрировать старые системы на базе 1С 7.7 с современными веб-сервисами и API, не опасаясь больших объемов данных.