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. Навряд чи якийсь один формат замінить усі інші. Розумніше обирати подання під те вузьке місце, яке у вас справді є.