Большой 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 в CLI + виртуализированный вьювер дерева | Редакторы начинают тормозить; 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-killer'ом»:
# Для файлов больше памяти: --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 или пагинацию и устраняйте гигантские массивы в источнике.
FAQ
Почему редактор открывает JSON десятки секунд, а программа парсит за 200 мс?
Парсинг — это нативный код, превращающий текст в структуру данных: 249 мс на нашей выборке 45 МБ. Редактор буксует на показе: пять миллионов строк вёрстки, подсветки и буфера отмены; дерево строит DOM на 3,5 миллиона узлов. Виртуализированный вьювер или прямое извлечение через jq обходит всё это.
Переполнится ли jq на JSON больше 1 ГБ?
В обычном режиме да: он грузит весь документ, а граф объектов достигает пика в 7-12× размера файла. С --stream ввод потребляется токен за токеном: наш тест на 45 МБ показал пик 3,6 МБ, и память остаётся плоской при любом размере файла — ценой единственного последовательного прохода.
Какого размера файл выдержат онлайн-инструменты?
Большинство комфортно до 2-5 МБ и заметно деградирует после 10 МБ. Жёсткий потолок — память вкладки (примерно 1-4 ГБ), но уже при нескольких десятках мегабайт ожидание парсинга и построения дерева мучительно. После 20 МБ — локальный инструмент или командная строка.
Как посмотреть значение одного поля в огромном JSON?
Извлекайте через jq, не открывая файл: jq -r '.[].email' huge.json выведет все адреса; с фильтром — jq -r '.[] | select(.active == true) | .email'. Для первых записей — jq '.[0:5]' huge.json, на порядки быстрее открытия файла.
Помогает ли форматирование перед открытием?
Нет. Форматирование превращает компактные 45 МБ в 71 МБ и одну строку в пять миллионов, добавляя редактору и вьюверу чистый оверхед. Форматируйте лишь то, что будет читать человек — и только если файл достаточно мал.