Работа с JSON в 1С 8.3 обычно строится на полной сериализации данных: мы считываем файл в Структуру или Соответствие, добавляем элемент и записываем всё обратно. Однако, если файл весит сотни мегабайт или гигабайты, этот подход становится невозможным из-за ограничений оперативной памяти и низкой производительности. В данной статье мы разберем способы, которые позволяют "дописывать" данные в JSON-файл, минимизируя нагрузку на систему.
Проанализируем самый надежный с точки зрения структуры способ. Вместо того чтобы загружать весь объект в память, мы будем использовать последовательное чтение и одновременную запись в новый (временный) файл. Как только мы дойдем до нужного места (например, перед закрывающей скобкой массива), мы вставим свои данные.
Рассмотрим пошагово, как реализовать этот алгоритм:
ЧтениеJSON.ЗаписьJSON.КонецМассива), мы сначала записываем свои новые данные, а затем закрывающее событие.Посмотрим на пример кода, реализующий этот подход:
// Путь к исходному файлу и временному файлу
ПутьКФайлу = "C:\temp\data.json";
ПутьКВременному = "C:\temp\data_temp.json";
Чтение = Новый ЧтениеJSON;
Чтение.ОткрытьФайл(ПутьКФайлу);
Запись = Новый ЗаписьJSON;
Запись.ОткрытьФайл(ПутьКВременному);
// Читаем всё до самого конца, пока не встретим закрывающую скобку основного массива
Пока Чтение.Прочитать() Цикл
// Если это конец корневого массива, и мы хотим добавить данные перед ним
Если Чтение.ТипТекущегоЗначения = ТипУзлаJSON.КонецМассива Тогда
// Здесь мы вставляем нашу новую структуру
НовыеДанные = Новый Структура("Дата, Событие", ТекущаяДата(), "Добавленная запись");
ЗаписатьJSON(Запись, НовыеДанные);
КонецЕсли;
// Транслируем текущее событие в новый файл
Запись.ЗаписатьСобытие(Чтение);
КонецЦикла;
Чтение.Закрыть();
Запись.Закрыть();
// Перемещаем временный файл на место старого
ПереместитьФайл(ПутьКВременному, ПутьКФайлу);
Важный нюанс: метод ЗаписатьСобытие позволяет сохранять исходную структуру и форматирование, не вникая в детали каждого свойства. Это наиболее безопасный способ для сохранения валидности JSON, а проверить результат визуально поможет просмотр JSON с форматированием и раскраской.
Выясним, можно ли вообще избежать сложного парсинга. Если вы проектируете систему с нуля или можете влиять на формат обмена, настоятельно рекомендуем использовать JSON Lines. В этом формате каждый объект занимает ровно одну строку и не оборачивается в общий массив или объект.
Разберем преимущества этого подхода: для добавления новой записи нам не нужно читать файл. Мы просто открываем его в режиме "Дозапись" и добавляем новую строку. Это работает мгновенно даже с файлами объемом в десятки гигабайт.
Пример добавления записи в формате JSONL:
НоваяЗапись = Новый Структура("id, status", 105, "Active");
// Используем ЗаписьТекста с параметром РежимДобавления
ТекстJSON = Новый ЗаписьТекста("C:\logs\events.jsonl", КодировкаТекста.UTF8, , Истина);
// Сериализуем объект в одну строку
ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыЗаписи = Новый ПараметрыЗаписиJSON(,,, ЭлементыРазделенияСтрокJSON.Нет);
ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписи);
ЗаписатьJSON(ЗаписьJSON, НоваяЗапись);
СтрокаДляЗаписи = ЗаписьJSON.Закрыть();
// Добавляем строку в конец файла
ТекстJSON.ЗаписатьСтроку(СтрокаДляЗаписи);
ТекстJSON.Закрыть();
Проанализируем ситуацию: при чтении такого файла вам нужно будет использовать ЧтениеТекста.ПрочитатьСтроку() и для каждой строки вызывать ПрочитатьJSON(). Это стандарт для систем логирования и высоконагруженных очередей.
Рассмотрим более экстремальный, но эффективный метод для классического JSON. Если файл представляет собой массив [...], мы можем программно "откатиться" на одну позицию назад, заменить закрывающую скобку ] на запятую ,, добавить данные и снова закрыть скобку.
Внимание: этот метод требует точного понимания кодировки. В UTF-8 без BOM символ ] занимает 1 байт. Мы можем использовать объект Файл и ФайловыйПоток (доступно в последних версиях платформы 8.3).
Разберем логику действий:
Посмотрим на примерный алгоритм (упрощенно):
// Работа через двоичные данные для точности
ФайлНаДиске = Новый Файл(ПутьКФайлу);
Размер = ФайлНаДиске.Размер();
// Открываем поток с возможностью записи
Поток = ФайлНаДиске.ОткрытьПоток(РежимОткрытияФайла.Открыть, ДоступКФайлу.ЧтениеИЗапись);
// Смещаемся к концу файла, чтобы найти ']'
Поток.Перейти(Размер - 1, ПозицияВПотоке.Начало);
// Здесь логика замены символа и дозаписи через ЗаписьДанных
// ...
Поток.Закрыть();
Этот метод считается "ювелирным", так как ошибка в один байт или неверная обработка BOM (Byte Order Mark) приведет к повреждению всего файла. Используйте его только в случае крайней необходимости, когда скорость критически важна.
Выясним причину, по которой JSON часто "ломается" при ручном добавлении текста. Платформа 1С при создании текстовых файлов часто добавляет в начало файла три невидимых байта — BOM. Если вы открываете файл на дозапись и 1С ошибочно решит, что это новый поток, она может вставить BOM прямо в середину файла.
Чтобы этого избежать, всегда явно указывайте кодировку КодировкаТекста.UTF8 и используйте методы работы с JSON, которые корректно обрабатывают стандарты кодирования. Помните, что стандарт JSON требует UTF-8, и наличие BOM часто не приветствуется внешними парсерами.
Подводя итог, выберем оптимальную стратегию:
ПрочитатьJSON / ЗаписатьJSON.Мы проанализировали основные способы работы с JSON-файлами в 1С 8.3. Выбор конкретного метода зависит от ваших требований к производительности и возможности изменения структуры данных.