JSON, JSONL и TOON: какой формат данных под какое узкое место
Сравниваем JSON, JSONL и TOON по тому, какую проблему решает каждый: примеры бок о бок, заметки об экономии токенов на входе LLM и подсказки, как выбрать.
Годами JSON был способом по умолчанию записывать структурированные данные. На нём держатся REST API, конфиги, базы данных, браузерные приложения и обмен между сервисами. Но то, как софт работает с данными, продолжает меняться. Датасеты огромные, события приходят потоками, а большие языковые модели теперь принимают структурированные данные на вход.
Из-за этого внимание привлекли ещё два формата: JSONL и TOON. На первый взгляд они похожи на соперников JSON, но каждый отвечает на свой вопрос. JSON создан для обмена структурированными данными. JSONL — для эффективной обработки независимых записей. TOON — чтобы данные в форме JSON становились компактнее и дешевле по токенам, когда их отправляют в LLM. Спрашивать, какой из них «лучше», — значит упускать суть. Полезнее понимать, для чего нужен каждый.
JSON: универсальная база
JSON, сокращение от JavaScript Object Notation, описывает данные объектами, массивами, строками, числами, булевыми значениями и null. Главная сила не в синтаксисе, а в экосистеме вокруг него: почти в каждом языке программирования есть библиотека для JSON, а веб-платформы поддерживают его нативно.
Типичный набор данных выглядит так:
{
"users": [
{
"id": 1,
"name": "Alice",
"role": "admin"
},
{
"id": 2,
"name": "Bob",
"role": "user"
}
]
}
Такая форма подходит приложению, которому нужно передать структурированную информацию, поэтому JSON хорошо ложится на REST API, конфигурацию, данные приложения и любые случаи, где вся структура разумного размера.
Проблемы начинаются, когда ту же форму растягивают на очень большие датасеты или когда LLM должна прочитать тысячи похожих объектов.
JSONL: одна запись на строку
JSONL расшифровывается как JSON Lines. Вместо того чтобы заворачивать все записи в один большой массив, он пишет полноценный JSON-объект на каждой строке. Тех же пользователей можно хранить так:
{"id":1,"name":"Alice","role":"admin"}
{"id":2,"name":"Bob","role":"user"}
{"id":3,"name":"Carol","role":"user"}
Каждая строка — независимая запись. Выглядит как мелкая правка синтаксиса, но она меняет то, как можно обращаться с данными. Большой JSON-массив может вынудить программу разобрать всю структуру, прежде чем она доберётся хоть до одной записи. С JSONL программа читает строку, парсит её, обрабатывает и переходит к следующей.
Сильнее всего это окупается на лог-файлах, потоках событий, обучающих наборах для ML, ETL-задачах и любых других данных, которые велики или постоянно растут. Возьмём датасет на 50 ГБ. Загружать его целиком как один гигантский объект почти никогда не нужно. С JSONL записи можно обрабатывать постепенно, и память уходит в основном на те записи, которые обрабатываются прямо сейчас.
То есть JSONL решает задачу обработки данных.
TOON: меньше токенов для модели
Теперь представьте другую проблему: нужно отправить в LLM тысячи структурированных записей. JSON справится, но в нём много пунктуации и повторяющихся имён:
{
"users": [
{"id": 1, "name": "Alice", "role": "admin"},
{"id": 2, "name": "Bob", "role": "user"},
{"id": 3, "name": "Carol", "role": "user"}
]
}
Посмотрите, как "id", "name" и "role" повторяются в каждом объекте. Обычному софту это почти безразлично. А вот для LLM все эти символы увеличивают число входных токенов.
Именно этот пробел закрывает TOON, Token-Oriented Object Notation. Это компактная и читаемая человеком кодировка модели данных JSON, рассчитанная в первую очередь на промпты и другие контексты, где важен расход токенов. Те же записи выглядят так:
users[3]{id,name,role}:
1,Alice,admin
2,Bob,user
3,Carol,user
Имена полей объявляются один раз, а дальше записи идут строками. Принцип простой: не повторять модели одну и ту же структуру снова и снова, а назвать её один раз и дать значения.
Какой вопрос задаёт каждый формат
Один из способов не путать эти три формата — посмотреть, что каждый пытается решить.
- JSON: как представить структурированные данные в формате, который поддерживают все.
- JSONL: как представить множество независимых записей, чтобы их можно было обрабатывать по частям.
- TOON: как компактнее записать данные в форме JSON, когда они отправляются в LLM.
Поэтому JSONL и TOON не заменяют друг друга. JSONL меняет то, как организованы записи. TOON меняет то, как представлены структурированные данные, ради экономии токенов. А JSON во многих таких процессах остаётся под ними как универсальный формат.
Сценарий первый: нагруженный пайплайн логов
Возьмём большую систему обработки логов, где каждую секунду появляются тысячи событий:
User logged in
Payment completed
Order created
Email sent
Если хранить эти события как отдельные JSON-объекты, по одному на строку, потребитель сможет обрабатывать их по мере поступления. Здесь JSONL и хорош. Он подходит для данных, которые велики, только дописываются, производятся непрерывно или по своей природе состоят из записей, так что его обычное место — логи, потоки событий, ML-пайплайны, ETL-системы и обработка больших данных.
JSON остаётся более естественным вариантом, когда вся структура — это один логический документ или когда приложения ждут обычный JSON API.
Сценарий второй: агент читает 10 000 клиентов
Теперь ИИ-агенту нужна информация о 10 000 клиентах. Если отправить её записями в стиле JSON, каждая строка повторяет свои ключи:
{"id":1,"name":"Alice","city":"Delhi"}
{"id":2,"name":"Bob","city":"Mumbai"}
{"id":3,"name":"Carol","city":"Pune"}
TOON может разложить однородную коллекцию в таблицу, указав имена полей один раз:
customers[3]{id,name,city}:
1,Alice,Delhi
2,Bob,Mumbai
3,Carol,Pune
Отсюда и берётся экономия токенов. Согласно спецификации, TOON — это построчная кодировка на отступах для той же модели данных, что и у JSON, и каждый массив объявляет свою длину и список полей лишь один раз.
Проект также приводит бенчмарки, где на тестовых датасетах TOON расходовал заметно меньше токенов, чем отформатированный JSON. Но сколько вы сэкономите, зависит от формы данных и от токенизатора. TOON не становится автоматически лучше для любого датасета. Больше всего он выигрывает на однородных массивах объектов с повторяющимися полями.
Заменит ли TOON JSON?
Сказать так заманчиво, но слишком просто. Сама спецификация подаёт TOON прежде всего как представление для данных в форме JSON. В ней сказано, что TOON не предназначен заменять JSON в универсальных API, а также в случаях с глубокой вложенностью или неоднородной структурой.
Реалистичный процесс оставляет JSON там, где он уже работает, и добавляет TOON только на границе с моделью:
Application data
↓
JSON
↓
Convert for LLM
↓
TOON
↓
LLM
JSON остаётся родным представлением приложения, а TOON становится форматом, в котором структурированные данные уходят в LLM. В этой роли TOON больше похож на слой перевода, чем на универсальную замену.
Использовать вместе
Эти форматы могут уживаться и в одной архитектуре. JSONL отвечает за то, как записи организованы и обрабатываются. TOON — за то, как эффективно представить структурированные данные для LLM. Приложение может выдавать большой поток записей в JSONL, обрабатывать их постепенно, отбирать нужное подмножество и уже его кодировать в TOON перед отправкой в модель.
Каждый формат снимает своё узкое место. JSONL помогает с обработкой записей в больших масштабах, TOON — с экономией токенов, а JSON — с универсальной совместимостью.
Как выбрать
Берите JSON, когда нужен широко поддерживаемый универсальный способ хранить структурированные данные. Публичные API, браузерные приложения, конфиги и датасеты скромного размера — очевидные случаи. Мало какой формат сравнится с ним по инструментам, а для небольшого обычного набора данных нет причин тащить что-то другое.
Присмотритесь к JSONL, когда данные — это груда независимых записей, которые хочется обрабатывать постепенно. Логи, потоки событий, обучающие данные для ML, ETL-пайплайны и большие датасеты — сильные примеры. Решающий вопрос: нужно ли обрабатывать весь датасет как одну структуру или достаточно по одной записи за раз. Если второе, JSONL стоит рассмотреть.
Присмотритесь к TOON, когда потребитель — LLM, а в данных много повторяющихся структурированных записей. Он подходит для однородных массивов, где одни и те же поля встречаются во множестве объектов, и именно это спецификация называет его сильной стороной. Глубоко вложенные или очень нерегулярные данные в JSON могут оказаться проще или даже меньше. Спросите себя, не тратятся ли токены на то, чтобы снова и снова описывать одну и ту же структуру. Если да, TOON заслуживает проверки.
Разное давление — разные форматы
JSON никуда не денется. Происходит другое: разные задачи с данными порождают специализированные форматы. JSON победил, потому что софту был нужен простой и совместимый способ описывать структурированные данные. JSONL вырос из необходимости работать с независимыми записями, особенно когда датасеты стали больше или пошли непрерывным потоком. TOON появился из-за ещё одного давления: LLM работают с токенами, и раз за разом отправлять служебный синтаксис стоит денег.
Так что правильная модель в голове — это не цепочка, в конце которой JSON умирает. Она такая: JSON для универсальной структуры, JSONL для обработки записей в больших масштабах, TOON для экономного по токенам входа LLM. Вряд ли какой-то один формат заменит все остальные. Разумнее выбирать представление под то узкое место, которое у вас действительно есть.