Великий JSON не відкривається: як обрати інструмент за розміром
Головне: Багатомегабайтні JSON-вивантаження часто підвішують текстові редактори й онлайн-інструменти, хоча сам парсинг триває кілька сотень мілісекунд. Ми виміряли час і пам'ять на кожному етапі для зразка 45 МБ і 500 000 записів, показали, що справжня вартість — це кількість рядків і вузлів, і склали таблицю вибору інструментів за розміром файлу: онлайн-перегляд, командний рядок, стрімінг і десктопні застосунки.

JSON-файл на 45 МБ парситься за 249 мілісекунд. Пів хвилини очікування дає рендеринг п'яти мільйонів рядків тексту та 3,5 мільйона вузлів дерева. Переплутаєте ці дві речі — і щоразу звинувачуватимете не того.
Один: спершу виміряти — парсинг ніколи не є вузьким місцем
Подвійний клік на багатомегабайтному .json-файлі, редактор крутиться тридцять секунд — і перша думка: «JSON парситься надто повільно». Виміри кажуть протилежне. На нашій машині (Node 22) ми згенерували зразок із 500 000 записів по п'ять полів (id, email, active, score, tags), 45 МБ у компактному вигляді:
| Операція | Результат вимірювання |
|---|---|
Повний JSON.parse |
249 мс |
JSON.stringify(data, null, 2) — красивий друк |
215 мс |
| Відформатований текст | 71 МБ, 5 000 001 рядок |
| Усього вузлів дерева (записи + поля) | близько 3 500 001 |
| RSS процесу Node після парсингу | 313 МБ (приблизно 7× розміру файлу) |
Парсинг завершився за чверть секунди. Парсер закінчив роботу раніше, ніж ви відпустили мишу. Усі наступні секунди пішли на шар «показати це людині»: текстовий редактор мусить розкласти п'ять мільйонів рядків, застосувати підсвічування та підтримувати буфер скасування; переглядач дерева мусить створити DOM-елемент для кожного з 3,5 мільйона вузлів — а браузери починають захлинатися біля сотні тисяч вузлів і втрачають відгук задовго до мільйона.
Висновок указує на цілком інший напрямок: не боріться з рендерингом — візьміть інструмент, який не рендерить усе одразу.
Два: чому воно висить — кількість рядків і вузлів є справжньою вартістю
Розмір файлу — лише поверхня. Інструменти ламають два похідні числа:
- Кількість рядків. 45 МБ компактного JSON після красивого друку — це п'ять мільйонів рядків. Ким би рядком ви не дивилися, редактор спершу мусить побудувати структуру рядків для всього файлу, розв'язати стан підсвічування й виділити буфери — витрати пропорційні загальній кількості рядків.
- Кількість вузлів. Пів мільйона записів × (один об'єкт + п'ять полів) — це 3,5 мільйона вузлів дерева. Будь-який переглядач, який будує все дерево перед показом, платить однакову пам'ять і час, чи розгортаєте ви одну гілку чи всі.
Звідси два неінтуїтивні наслідки. Форматувати перед переглядом — собі на шкоду: файл росте з 45 до 71 МБ, кількість рядків зростає у сорок разів, тиснучи на інструмент суто додатковим навантаженням. Пропускати файл через cat у термінал — теж собі на шкоду: буфер прокрутки стає новим вузьким місцем; якщо потрібні перші байти, вистачить head -c 2000.
Три: вибирати інструмент за розміром — таблиця рішень
Різним розмірам відповідають цілком різні інструменти. Поєднавши виміри вище з опублікованими орієнтирами (OpenFormatter ставить комфортну зону онлайн-інструментів у 2-5 МБ; PureJSON оцінює пам'ять після парсингу 500 МБ документа у 2-4 ГБ), отримуємо таку таблицю:
| Розмір файлу | Перший вибір | Чому |
|---|---|---|
| < 2 МБ | Будь-який онлайн-інструмент | Миттєвий доступ; деревовидний перегляд і валідація в стилі /parse за один крок |
| 2 – 20 МБ | Локальний редактор (VS Code) або браузерний локальний інструмент | Онлайн-інструменти починають деградувати; локальна обробка не відправляє дані |
| 20 – 100 МБ | Розвідка через jq + віртуалізований переглядач дерева | Редактори починають гальмувати; jq витягує будь-який фрагмент за секунди |
| 100 МБ – 1 ГБ | jq --stream / ijson, потокова обробка |
Звичайний парсинг їсть пам'ять до ~7× розміру файлу; не вміщується — стрімте |
| > 1 ГБ або постійне доповнення | Змінити формат: NDJSON / CSV / Parquet | Один велетенський масив треба повністю розпарсити, щоб побачити перший запис; проблема вже у форматі |
Інструмент /parse на цьому сайті покриває перший щабель — деревовидний перегляд і валідацію. Для більших файлів беріть десктопний застосунок, щоб десятки мегабайтів не потрапляли на вебсторінку.
Чотири: не відкривайте файл — спершу спитайте про структуру
Отримавши незнайомий великий JSON, перший крок — не відкриття, а кілька секунд на з'ясування структури. jq відповідає на три питання приблизно за 200 мс:
# Масив чи об'єкт угорі? Скільки записів?
jq 'if type == "array" then {type: "array", count: length} else {type: "object", keys: (keys|length)} end' huge.json
# Як виглядає перший запис (один запис, без потоку тексту)?
jq '.[0]' huge.json | head -40
# Усі назви полів (з першого запису)
jq '.[0] | keys' huge.json
Щойно структура відома, більшість запитів зводиться до «витягти поле» — файл взагалі не треба відкривати. Наприклад, потрібна лише електронна пошта всіх користувачів:
jq -r '.[].email' huge.json | less
# Додайте фільтр
jq -r '.[] | select(.active == true) | .email' huge.json
Правило просте: для «погляду» — переглядач із віртуалізованим рендерингом; для «пошуку та витягання» — jq. Не змішуйте ці дві роботи в одному інструменті.
П'ять: пам'ятний обрив — звичайний режим проти потокового, різниця у 150 разів
На тому самому зразку 45 МБ /usr/bin/time -v виміряв пікову пам'ять jq у двох режимах:
| Режим | Команда | Пік пам'яті (RSS) | Час |
|---|---|---|---|
| Звичайний (повне завантаження) | jq '.[0].email' sample.json |
542 МБ | 0,7 с |
| Потоковий | jq --stream 'select(.[0][1]=="email") | .[1]' sample.json |
3,6 МБ | 2,5 с |
Звичайний режим читає весь файл і будує граф об'єктів; пік 542 МБ підтверджує правило «граф об'єктів ≈ 7-12× тексту». --stream споживає вхід токен за токеном, тримаючи пам'ять на рівні одиниць МБ — ціною повільнішого загального часу. За межею гігабайта ця різниця розділяє «працює» та «вбитий OOM-кілером»:
# Для файлів більших за пам'ять: --stream — єдиний режим, що ніколи не вантажить усе
jq --stream -n 'fromstream(1|truncate_stream(inputs))' huge.json
Python-еквівалент — ijson: ijson.items(f, 'item') видає елементи масиву по одному з такою ж сталою пам'яттю. Спільна плата цих інструментів — відмова від довільного доступу: потік — це один прохід уперед, і повторний прохід означає повторне читання файлу.
Шість: скільки може показати браузер — межі локальної обробки
Онлайн-інструментами можна користуватися, але в межах. Сучасна вкладка браузера має приблизно 1-4 ГБ пам'яті; файл на 45 МБ, розпарсений у граф плюс дерево, зазвичай виживає. Кілька сотень мегабайт — уже край урвища. Обираючи онлайн-переглядач, вимагайте трьох речей:
- Обробка відбувається локально (вставлений текст не надсилається на сервер) — це і захист даних, і економія часу завантаження; усі інструменти цього сайту працюють цілком у браузері й доступні офлайн;
- Парсинг іде у Web Worker — головний потік не заморожується, а зависання коштує вкладки, а не всього браузера;
- Дерево віртуалізоване або ліниве — згорнуті гілки майже нічого не коштують, рендериться лише розгорнуте.
На цьому сайті: /parse підходить для розвідки структури й пошуку помилок у файлах до кількох десятків мегабайт; усе більше — jq або десктопний застосунок, а браузер лишається для малих фрагментів.
Сім: оберіть правильний формат — і половина проблем зникне
Якщо ви впливаєте на те, як файл створюється, кращий переглядач — неправильне лікування. Зробіть так, щоб файл не виростав у «один велетенський масив»:
- NDJSON/JSONL: один запис на рядок. Дозапис не переписує файл,
head,grep,tail,splitпрацюють напряму; обрізаний файл втрачає лише останній рядок. У нашому довіднику JSONL є повна процедура розбору зіпсованих рядків. - Пагінація вивантажень: API на 100 000 записів має приймати параметри пагінації — по 100 за раз зручніше обом сторонам.
- Табличні дані — не JSON: один запис на рядок, фіксовані поля без вкладень — це таблиця. CSV або Parquet менші й мають багатшу екосистему.
Цифра, яку варто запам'ятати: розріжте навпіл масив на 500 000 записів — перша половина лишиться коректним NDJSON-файлом (половина записів жива), тоді як відповідний одиночний велетенський масив пропадає повністю. 500 відновлених записів із 501 — краще за нуль.
Вісім: чекліст
- Спершу з'ясуйте структуру через
jq '.[0] | keys'або вибірку на 500 записів; - Ніколи не форматуйте файл лише для того, щоб його відкрити — подвоєння рядків лише сповільнить роботу;
- До 2 МБ — онлайн-переглядачі; понад 20 МБ — командний рядок; понад 1 ГБ — завжди
--streamабо ijson; - Перевіряйте, що онлайн-інструмент обробляє локально (вставлений текст не лишає браузер);
- Якщо контролюєте генератора — переходьте на NDJSON або пагінацію й усувайте велетенські масиви в джерелі.
Часті запитання
Чому редактор відкриває JSON десятки секунд, а програма парсить за 200 мс?
Парсинг — це нативний код, що перетворює текст на структуру даних: 249 мс для зразка 45 МБ. Редактор гальмує на показі: п'ять мільйонів рядків на розкладку, підсвічування й буфер скасування; дерево — DOM на 3,5 мільйона вузлів. Віртуалізований переглядач або пряме витягання через jq обходить усе це.
Чи переповниться jq на JSON понад 1 ГБ?
Звичайний режим — так: він вантажить увесь документ, а граф об'єктів сягає піку в 7-12× розміру файлу. З --stream вхід споживається токен за токеном: наш тест на 45 МБ показав пік 3,6 МБ, і пам'ять не росте з розміром файлу — ціною одного послідовного проходу.
Якого розміру файл витримають онлайн-інструменти?
Більшість онлайн-інструментів комфортні до 2-5 МБ і помітно деградують після 10 МБ. Жорстка стеля — пам'ять вкладки (приблизно 1-4 ГБ), але вже за кілька десятків мегабайт очікування парсингу та побудови дерева болить. Понад 20 МБ — беріть локальний інструмент або CLI.
Як глянути значення одного поля у величезному JSON?
Витягуйте jq, не відкриваючи файл: jq -r '.[].email' huge.json виведе всі email; з фільтром — jq -r '.[] | select(.active == true) | .email'. Для перших записів — jq '.[0:5]' huge.json, на порядки швидше за відкриття файлу.
Чи допоможе форматування перед відкриттям?
Ні. Форматування перетворює компактні 45 МБ на 71 МБ і один рядок на п'ять мільйонів, додаючи редакторові та переглядачу чистий оверхед. Форматуйте лише те, що людина читатиме, — і лише якщо файл досить малий.