DevToys Web Pro iconDevToys Web ProБлог
Переведено с помощью LocalePack logoLocalePack
Оцените нас:
Попробуйте расширение для браузера:
← Назад к блогу

Полное руководство по форматированию JSON: красиво, минимально, валидно

12 мин чтения

JSON — универсальный язык API, конфигурационных файлов и обмена данными. Но сырой JSON из ответа API часто представляет собой одну нечитаемую строку, а JSON, написанный вручную, иногда содержит незаметные ошибки, которые всплывают только в runtime. Хороший форматтер делает три вещи: делает JSON читаемым, компактным для передачи и выявляет ошибки до попадания в продакшн. Откройте Форматтер JSON по ходу чтения.

Pretty-print против минификации: когда что использовать

Один и тот же объект JSON можно представить в двух крайних формах:

// Минифицированный — для передачи и хранения
{"user":{"id":42,"name":"Иван Иванов","active":true,"roles":["admin","editor"]}}
// Pretty-print — для чтения и редактирования
{
  "user": {
    "id": 42,
    "name": "Иван Иванов",
    "active": true,
    "roles": [
      "admin",
      "editor"
    ]
  }
}
РежимИспользуйте когдаИзбегайте когда
Pretty-printОтладка API-ответов, редактирование конфигов, ревью кода, документация, сравнение двух JSON-пейлоадовОтправка по сети, хранение в БД, встраивание в JS-бандлы
МинификацияAPI-ответы, localStorage, куки, query-параметры, CI-артефактыФайлы, которые человек читает или редактирует напрямую

Разница в размере важна в масштабе. API-ответ 50 КБ в pretty-print минифицируется до ~35 КБ — сокращение на 30% без потери информации. При миллионах запросов в день это ощутимо.

Отступы: 2 пробела, 4 пробела или табуляция

Pretty-print требует выбора единицы отступа. Универсального стандарта для JSON нет, но сложились контекстные соглашения:

ОтступРаспространён вКомпромисс
2 пробелаJavaScript-экосистема, package.json, большинство REST API, стандарт PrettierКомпактно; глубокая вложенность укладывается в 80 символов
4 пробелаPython (json.dumps по умолчанию), Java-инструментыЧитабельнее на малой глубине; глубокая вложенность уходит вправо
ТабуляцияНекоторые Go-инструменты, редакторы с настройкой ширины табаВизуально адаптируется под редактор; непоследовательно в diff-вьюерах

В JavaScript JSON.stringify принимает необязательный третий аргумент для отступа:

const obj = { name: "Иван", active: true };

JSON.stringify(obj);             // минифицировано: '{"name":"Иван","active":true}'
JSON.stringify(obj, null, 2);   // отступ 2 пробела
JSON.stringify(obj, null, 4);   // отступ 4 пробела
JSON.stringify(obj, null, '	'); // отступ табуляцией

JSON5 и JSONC: комментарии и хвостовые запятые

Стандартный JSON (ECMA-404) не допускает комментариев и хвостовых запятых — это намеренно: JSON является форматом обмена данными, а не языком конфигурации. Но конфигурационные файлы пишутся людьми, а люди хотят комментарии.

Два нестандартных надмножества заполняют этот пробел:

JSONC (JSON с комментариями)

Используется VS Code (settings.json, launch.json), TypeScript (tsconfig.json) и ESLint. Поддерживает комментарии // и /* */, а также хвостовые запятые:

// tsconfig.json — это JSONC
{
  "compilerOptions": {
    "target": "ES2022",     // минимум Node 18
    "strict": true,
    "moduleResolution": "bundler",
    /* включает path aliases */
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],   // хвостовая запятая допустима в JSONC
    },
  },
}

JSON5

Более либеральное надмножество: также разрешает неэкранированные ключи, строки в одинарных кавычках, шестнадцатеричные числа, многострочные строки и +Infinity / -Infinity.

Если вставить JSONC или JSON5 в строгий JSON-валидатор, он отклонит комментарии и хвостовые запятые. Форматтер JSON обрабатывает оба формата — удаляет комментарии и хвостовые запятые перед парсингом. Подробнее в статье Хвостовые запятые и комментарии в JSON.

Валидация: что делает JSON невалидным

JSON имеет строгие правила синтаксиса. Вот самые частые ошибки:

1. Хвостовые запятые

// Невалидный JSON — хвостовая запятая после последнего элемента
{
  "name": "Иван",
  "active": true,    ошибка
}

2. Одинарные кавычки вместо двойных

// Невалидно — JSON требует двойные кавычки
{ 'name': 'Иван' }

// Валидно
{ "name": "Иван" }

3. Ключи без кавычек

// Невалидно — все ключи должны быть строками в кавычках
{ name: "Иван" }

// Валидно
{ "name": "Иван" }

4. Комментарии

// Невалидно — в JSON нет синтаксиса комментариев
{
  // Это объект пользователя
  "name": "Иван"
}

5. undefined, NaN, Infinity

// Невалидно — эти JavaScript-значения не представимы в JSON
{
  "value": undefined,
  "ratio": NaN,
  "limit": Infinity
}

// Валидные альтернативы
{
  "value": null,
  "ratio": null,
  "limit": 1.7976931348623157e+308
}

6. Неэкранированные управляющие символы в строках

// Невалидно — символ переноса строки внутри строки
{ "text": "строка первая
строка вторая" }

// Валидно — используйте escape-последовательности
{ "text": "строка первая
строка вторая" }

7. Числа с ведущими нулями

// Невалидно — JSON запрещает ведущие нули (восьмеричная неоднозначность)
{ "code": 007 }

// Валидно
{ "code": 7 }

Сортировка ключей

Объекты JSON технически неупорядочены — спецификация не гарантирует порядок ключей. На практике большинство парсеров сохраняют порядок вставки, но полагаться на это не стоит.

Сортировка ключей полезна для:

  • Сравнения (diff): Два JSON-объекта с одинаковыми данными, но разным порядком ключей, дают «шумный» diff. Отсортируйте оба перед сравнением.
  • Кэширования: Если вы хэшируете JSON как ключ кэша, несортированные ключи могут давать разные хэши для идентичных данных.
  • Консистентности в git: Отсортированные ключи означают, что git diff показывает только изменения данных, а не перестановки.
// Рекурсивная сортировка ключей
function sortKeys(obj) {
  if (Array.isArray(obj)) return obj.map(sortKeys);
  if (obj !== null && typeof obj === 'object') {
    return Object.fromEntries(
      Object.entries(obj)
        .sort(([a], [b]) => a.localeCompare(b))
        .map(([k, v]) => [k, sortKeys(v)])
    );
  }
  return obj;
}

const sorted = JSON.stringify(sortKeys(data), null, 2);

В командной строке jq сортирует ключи флагом --sort-keys:

jq --sort-keys . input.json > sorted.json

Работа с большими JSON-файлами

Вставить файл 10 МБ в браузерный форматтер — можно, но парсинг и рендеринг большого дерева может быть медленным. Для больших файлов быстрее использовать консольные инструменты:

# Pretty-print
jq . large.json

# Минификация
jq -c . large.json

# Извлечь вложенное значение
jq '.users[0].profile.name' large.json

# Фильтрация массива
jq '[.users[] | select(.active == true)]' large.json

Форматирование JSON в коде

JavaScript / TypeScript

// Pretty-print
const pretty = JSON.stringify(data, null, 2);

// Минификация
const minified = JSON.stringify(data);

// С replacer — исключить null-значения
const clean = JSON.stringify(data, (key, value) =>
  value === null ? undefined : value
, 2);

// Безопасный парсинг
function safeParseJSON(str) {
  try {
    return { ok: true, data: JSON.parse(str) };
  } catch (e) {
    return { ok: false, error: e.message };
  }
}

Python

import json

# Pretty-print
print(json.dumps(data, indent=2, ensure_ascii=False))

# Минификация (без пробелов)
print(json.dumps(data, separators=(',', ':')))

# Сортировка ключей
print(json.dumps(data, indent=2, sort_keys=True))

# Парсинг с обработкой ошибок
try:
    parsed = json.loads(raw_string)
except json.JSONDecodeError as e:
    print(f"Ошибка JSON в строке {e.lineno}, столбце {e.colno}: {e.msg}")

Двойное кодирование JSON

Частая ловушка: JSON из API иногда двойно закодирован — объект JSON сериализован в строку, и эта строка является значением в другом JSON:

// Двойное кодирование: значение — строка, содержащая JSON
{
  "payload": "{"user":{"id":42,"name":"Иван"}}"
}

Чтобы работать с внутренним JSON, нужно парсить дважды — или использовать Разэкранирование строк JSON для извлечения внутреннего пейлоада.

Краткая справка

ЗадачаИнструмент
Pretty-print или минификация JSONФорматтер JSON
Валидация и просмотр точной ошибкиФорматтер JSON
Разэкранирование двойно закодированной строкиРазэкранирование JSON
Запросы к вложенным значениям через dot-pathJSONPath Tester
Конвертация JSON в CSV для таблицJSON ↔ CSV Конвертер
Валидация JSON по схемеВалидатор JSON Schema

Форматируйте, валидируйте и изучайте JSON прямо в браузере с помощью Форматтера JSON — данные не покидают ваш компьютер.