Как в 1С 8.3 добавить записи в JSON-файл без удаления старых данных?

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

Работа с JSON в 1С 8.3 обычно строится на полной сериализации данных: мы считываем файл в Структуру или Соответствие, добавляем элемент и записываем всё обратно. Однако, если файл весит сотни мегабайт или гигабайты, этот подход становится невозможным из-за ограничений оперативной памяти и низкой производительности. В данной статье мы разберем способы, которые позволяют "дописывать" данные в JSON-файл, минимизируя нагрузку на систему.

Метод 1. Потоковая трансляция через ЧтениеJSON и ЗаписьJSON

Проанализируем самый надежный с точки зрения структуры способ. Вместо того чтобы загружать весь объект в память, мы будем использовать последовательное чтение и одновременную запись в новый (временный) файл. Как только мы дойдем до нужного места (например, перед закрывающей скобкой массива), мы вставим свои данные.

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

  1. Открываем существующий файл через объект ЧтениеJSON.
  2. Создаем новый временный файл через объект ЗаписьJSON.
  3. В цикле читаем события из источника и сразу записываем их в приемник.
  4. При обнаружении конца корневого узла (например, КонецМассива), мы сначала записываем свои новые данные, а затем закрывающее событие.

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


// Путь к исходному файлу и временному файлу
ПутьКФайлу = "C:\temp\data.json";
ПутьКВременному = "C:\temp\data_temp.json";

Чтение = Новый ЧтениеJSON;
Чтение.ОткрытьФайл(ПутьКФайлу);

Запись = Новый ЗаписьJSON;
Запись.ОткрытьФайл(ПутьКВременному);

// Читаем всё до самого конца, пока не встретим закрывающую скобку основного массива
Пока Чтение.Прочитать() Цикл
    // Если это конец корневого массива, и мы хотим добавить данные перед ним
    Если Чтение.ТипТекущегоЗначения = ТипУзлаJSON.КонецМассива Тогда
        // Здесь мы вставляем нашу новую структуру
        НовыеДанные = Новый Структура("Дата, Событие", ТекущаяДата(), "Добавленная запись");
        ЗаписатьJSON(Запись, НовыеДанные);
    КонецЕсли;
    
    // Транслируем текущее событие в новый файл
    Запись.ЗаписатьСобытие(Чтение);
КонецЦикла;

Чтение.Закрыть();
Запись.Закрыть();

// Перемещаем временный файл на место старого
ПереместитьФайл(ПутьКВременному, ПутьКФайлу);

Важный нюанс: метод ЗаписатьСобытие позволяет сохранять исходную структуру и форматирование, не вникая в детали каждого свойства. Это наиболее безопасный способ для сохранения валидности JSON, а проверить результат визуально поможет просмотр JSON с форматированием и раскраской.

Метод 2. Использование формата JSON Lines (NDJSON)

Выясним, можно ли вообще избежать сложного парсинга. Если вы проектируете систему с нуля или можете влиять на формат обмена, настоятельно рекомендуем использовать JSON Lines. В этом формате каждый объект занимает ровно одну строку и не оборачивается в общий массив или объект.

Разберем преимущества этого подхода: для добавления новой записи нам не нужно читать файл. Мы просто открываем его в режиме "Дозапись" и добавляем новую строку. Это работает мгновенно даже с файлами объемом в десятки гигабайт.

Пример добавления записи в формате JSONL:


НоваяЗапись = Новый Структура("id, status", 105, "Active");

// Используем ЗаписьТекста с параметром РежимДобавления
ТекстJSON = Новый ЗаписьТекста("C:\logs\events.jsonl", КодировкаТекста.UTF8, , Истина);

// Сериализуем объект в одну строку
ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыЗаписи = Новый ПараметрыЗаписиJSON(,,, ЭлементыРазделенияСтрокJSON.Нет);
ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписи);
ЗаписатьJSON(ЗаписьJSON, НоваяЗапись);

СтрокаДляЗаписи = ЗаписьJSON.Закрыть();

// Добавляем строку в конец файла
ТекстJSON.ЗаписатьСтроку(СтрокаДляЗаписи);
ТекстJSON.Закрыть();

Проанализируем ситуацию: при чтении такого файла вам нужно будет использовать ЧтениеТекста.ПрочитатьСтроку() и для каждой строки вызывать ПрочитатьJSON(). Это стандарт для систем логирования и высоконагруженных очередей.

Метод 3. Низкоуровневая работа с файловым потоком (Смещение указателя)

Рассмотрим более экстремальный, но эффективный метод для классического JSON. Если файл представляет собой массив [...], мы можем программно "откатиться" на одну позицию назад, заменить закрывающую скобку ] на запятую ,, добавить данные и снова закрыть скобку.

Внимание: этот метод требует точного понимания кодировки. В UTF-8 без BOM символ ] занимает 1 байт. Мы можем использовать объект Файл и ФайловыйПоток (доступно в последних версиях платформы 8.3).

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

  1. Открываем файл для чтения и записи.
  2. Устанавливаем позицию курсора в конец файла минус 1 или 2 байта (зависит от наличия символов перевода строк).
  3. Проверяем, что там действительно закрывающая скобка.
  4. Записываем запятую, затем сериализованный JSON нового объекта, затем снова закрывающую скобку.

Посмотрим на примерный алгоритм (упрощенно):


// Работа через двоичные данные для точности
ФайлНаДиске = Новый Файл(ПутьКФайлу);
Размер = ФайлНаДиске.Размер();

// Открываем поток с возможностью записи
Поток = ФайлНаДиске.ОткрытьПоток(РежимОткрытияФайла.Открыть, ДоступКФайлу.ЧтениеИЗапись);
// Смещаемся к концу файла, чтобы найти ']'
Поток.Перейти(Размер - 1, ПозицияВПотоке.Начало); 

// Здесь логика замены символа и дозаписи через ЗаписьДанных
// ...
Поток.Закрыть();

Этот метод считается "ювелирным", так как ошибка в один байт или неверная обработка BOM (Byte Order Mark) приведет к повреждению всего файла. Используйте его только в случае крайней необходимости, когда скорость критически важна.

Проблема кодировки и меток BOM

Выясним причину, по которой JSON часто "ломается" при ручном добавлении текста. Платформа 1С при создании текстовых файлов часто добавляет в начало файла три невидимых байта — BOM. Если вы открываете файл на дозапись и 1С ошибочно решит, что это новый поток, она может вставить BOM прямо в середину файла.

Чтобы этого избежать, всегда явно указывайте кодировку КодировкаТекста.UTF8 и используйте методы работы с JSON, которые корректно обрабатывают стандарты кодирования. Помните, что стандарт JSON требует UTF-8, и наличие BOM часто не приветствуется внешними парсерами.

Практические советы

Подводя итог, выберем оптимальную стратегию:

Мы проанализировали основные способы работы с JSON-файлами в 1С 8.3. Выбор конкретного метода зависит от ваших требований к производительности и возможности изменения структуры данных.

← На главную