EMZETT.
Войти

JSONL (JSON Lines)

Коротко: Формат файла, в котором каждая строка сама по себе является полным допустимым объектом JSON — в отличие от обычного файла JSON, который в целом должен быть одним объектом или массивом.

Подробнее: Удобен для журналов и потоков, так как можно читать и писать построчно, не разбирая весь файл, а новые записи просто дописываются в конец.

Наш контекст: Claude Code хранит стенограммы сеансов в формате JSONL (одна строка на событие: сообщение пользователя, ответ ассистента, вызов инструмента, …) в ~/.claude/projects/<проект>/<идентификатор-сеанса>.jsonl. Хук Stop, который впоследствии был убран, обращался к этим файлам.

Подробности

Дописывание вместо перезаписи

Преимущество JSONL перед одним большим файлом JSON особенно заметно в очень длинных или растущих потоках данных: запись журнала может просто дописывать каждую новую строку в конец файла (fs.appendFile), не читая, не разбирая, не изменяя и не перезаписывая весь существующий файл — с обычным файлом JSON (который в целом должен быть допустимым массивом/объектом) это было бы необходимо, например, чтобы добавить новый элемент в конец массива. Для файла журнала в несколько гигабайт эта разница не просто неудобна, а практически значима: полная перезапись для каждой новой записи становилась бы всё медленнее по мере роста файла, тогда как дописывание остаётся постоянно быстрым независимо от размера существующего файла.

Построчная обработка без загрузки всего

Построчная обработка (вместо загрузки всего в память сразу) также проще:

const readline = require("readline");
const stream = readline.createInterface({ input: fs.createReadStream("session.jsonl") });
for await (const line of stream) {
  const event = JSON.parse(line);
  // ... обработка построчно, не держа весь файл в памяти
}

Это особенно важно для файлов, которые могут стать больше доступной памяти — JSON.parse() всего многогигабайтного файла либо занял бы очень много времени, либо сразу завершился бы ошибкой нехватки памяти, тогда как построчная обработка требует постоянно небольшого объёма памяти независимо от общего размера файла.

Отказоустойчивость

Недостаток классических файлов JSON в этом контексте: в JSONL одну повреждённую строку (например, из-за прерванной записи, скажем, из-за сбоя процесса посреди записи) можно пропустить изолированно, не делая нечитаемым весь файл — в классическом файле JSON один испорченный символ где-то посередине приведёт к сбою разбора всего файла, даже если 99 % содержимого на самом деле целы. Это свойство делает JSONL особенно надёжным для случаев, когда запись может быть прервана (например, сбой системы или внезапное завершение процесса).

Распространённые области применения

Помимо стенограмм сеансов JSONL часто используется для обучающих данных в машинном обучении (каждая строка — один обучающий пример), для агрегации журналов (каждая строка — одно событие журнала, часто с единообразными полями вроде метки времени и уровня журнала) и для обмена данными между системами, где записи должны обрабатываться по отдельности и независимо друг от друга — например, при потоковой передаче экспорта базы данных, где каждая строка представляет одну запись.

См. также: Claude Code Hooks, JSON