JSON Formatter Python — Руководство json.dumps()

·Backend Developer·ПровереноDmitri Volkov·Опубликовано

Используйте бесплатный JSON Formatter & Beautifier прямо в браузере — установка не требуется.

Попробовать JSON Formatter & Beautifier онлайн →

Когда я отлаживаю Python API-клиент, первое, к чему я обращаюсь, — это python pretty print json — один вызов json.dumps(data, indent=4) и нечитаемый однострочный blob мгновенно становится удобным для навигации. Встроенный json модуль Python решает эту задачу полностью в рамках стандартной библиотеки — без сторонних установок. Если нужен быстрый результат без написания кода, JSON Formatter от ToolDeck сделает это мгновенно. Это руководство охватывает все практические методы: json.dumps() со всеми параметрами, pprint, orjson для высокопроизводительного форматирования, json.tool CLI, и реальные сценарии — форматирование API-ответов и чтение с диска — всё с кодом, совместимым с Python 3.8+. Также рассматривается сериализация пользовательских типов вроде datetime и UUID, потоковая обработка файлов гигабайтного размера с помощью ijson, и подсветка синтаксиса в терминале с rich.

Ключевые выводы
  • json.dumps(data, indent=4) встроен в stdlib Python начиная с 2.6 — установка не нужна.
  • Передавайте ensure_ascii=False всякий раз, когда данные содержат буквы с диакритикой, символы CJK или emoji.
  • Для datetime, UUID и пользовательских классов используйте параметр default= или создайте подкласс json.JSONEncoder.
  • separators=(',', ':') убирает все пробелы — используйте для сетевой передачи или встраивания в URL.
  • orjson работает в 5–10× быстрее stdlib и нативно поддерживает datetime и uuid.UUID.
  • pprint.pprint() выводит Python-синтаксис (True/None), а не валидный JSON — никогда не используйте для файлов или API-ответов.
  • Для JSON-файлов размером более 50 МБ используйте потоковую обработку через ijson вместо json.load(), чтобы избежать MemoryError.

Что такое JSON Pretty Printing?

Pretty printing преобразует плотную минифицированную JSON-строку в удобочитаемый формат с последовательными отступами и переносами строк. Преобразование носит исключительно косметический характер: данные идентичны, меняется только представление. Модуль json Python решает эту задачу целиком в рамках стандартной библиотеки — ничего устанавливать не нужно.

Before · json
After · json
{"id":"usr_9f3a2b","name":"Иван Петров","roles":["admin","editor"],"prefs":{"theme":"dark","lang":"ru"}}
{
    "id": "usr_9f3a2b",
    "name": "Иван Петров",
    "roles": [
        "admin",
        "editor"
    ],
    "prefs": {
        "theme": "dark",
        "lang": "ru"
    }
}

json.dumps() — стандартный способ форматирования JSON

json.dumps() входит в стандартную библиотеку Python начиная с версии 2.6 — просто import json, никакой установки не нужно. Сериализует любой JSON-совместимый Python-объект в форматированную строку. Ключевой параметр — indent: установите в 4 (или 2), чтобы получить читаемый вывод.

Python 3.8+ — минимальный пример
import json

user = {
    "id": "usr_9f3a2b",
    "name": "Иван Петров",
    "roles": ["admin", "editor"],
    "prefs": {"theme": "dark", "lang": "ru"}
}

print(json.dumps(user, indent=4, ensure_ascii=False))
# Output:
# {
#     "id": "usr_9f3a2b",
#     "name": "Иван Петров",
#     "roles": [
#         "admin",
#         "editor"
#     ],
#     "prefs": {
#         "theme": "dark",
#         "lang": "ru"
#     }
# }

Для продакшн-использования часто нужны sort_keys=True (стабильный вывод между запусками) и ensure_ascii=False (сохранять не-ASCII символы в читаемом виде):

Python 3.8+ — с sort_keys и ensure_ascii
import json

api_response = {
    "timestamp": "2024-05-01T10:30:00Z",
    "status": "success",
    "data": {
        "user_id": "usr_9f3a2b",
        "display_name": "Анна Смирнова",
        "score": 4892.5,
        "tags": ["python", "backend", "api"]
    }
}

print(json.dumps(api_response, indent=4, sort_keys=True, ensure_ascii=False))
# Output (ключи отсортированы, кириллица сохранена):
# {
#     "data": {
#         "display_name": "Анна Смирнова",
#         "score": 4892.5,
#         "tags": ["api", "backend", "python"],
#         "user_id": "usr_9f3a2b"
#     },
#     "status": "success",
#     "timestamp": "2024-05-01T10:30:00Z"
# }
Примечание:json.dumps() возвращает строку. Чтобы записать форматированный JSON напрямую в файл, используйте json.dump(data, f, indent=4) (без s) — записывает в файловый объект и не создаёт промежуточную строку в памяти.

Справочник параметров json.dumps()

Все параметры, кроме самого объекта, являются необязательными. По умолчанию создаётся компактный ASCII-безопасный JSON — передавайте параметры явно для удобочитаемого вывода.

Параметр
Тип
По умолчанию
Описание
obj
any
Объект Python для сериализации в строку формата JSON.
indent
int | str | None
None
Пробелов на уровень отступа. None = компактная одна строка, 0 = только переносы строк, 4 = стандарт.
sort_keys
bool
False
Сортировать ключи словаря в алфавитном порядке на всех уровнях вложенности.
ensure_ascii
bool
True
Экранировать не-ASCII символы в \uXXXX. Передайте False для сохранения Unicode-символов как есть.
separators
tuple | None
None
Пара (sep_элементов, sep_ключей). Используйте (",", ":") для максимально компактного вывода без пробелов.
default
callable | None
None
Вызывается для типов, не сериализуемых по умолчанию. Выбросьте TypeError для отклонения значения.
allow_nan
bool
True
Сериализовать float("nan") и float("inf") как JS-литералы. Передайте False, чтобы выбрасывался ValueError.

Компактный вывод JSON с параметром separators

По умолчанию json.dumps() разделяет элементы через ", " и ключи от значений через ": ". Параметр separators переопределяет оба. Передача (',', ':') убирает все пробелы для получения максимально компактного валидного JSON — удобно для сетевой передачи, встраивания в URL или хранения JSON в колонке базы данных, где важен каждый байт.

Python 3.8+
import json

payload = {
    "endpoint": "/api/v2/events",
    "filters": {"status": "active", "limit": 100},
    "sort": "desc"
}

# По умолчанию — пробелы после разделителей (читаемо)
default_out = json.dumps(payload)
# {"endpoint": "/api/v2/events", "filters": {"status": "active", "limit": 100}, "sort": "desc"}
# len = 88

# Компактно — без пробелов вообще
compact_out = json.dumps(payload, separators=(',', ':'))
# {"endpoint":"/api/v2/events","filters":{"status":"active","limit":100},"sort":"desc"}
# len = 80  (на 9% меньше; экономия растёт на больших, глубоко вложенных payload)

# Компактно + отсортированные ключи для воспроизводимых ключей кэша или хэшей содержимого
canonical = json.dumps(payload, separators=(',', ':'), sort_keys=True)
print(canonical)
# {"endpoint":"/api/v2/events","filters":{"limit":100,"status":"active"},"sort":"desc"}
Примечание:Когда вы передаёте indent= вместе с separators=, аргумент separators управляет только встроенными разделителями — переносы строк и отступы от indent сохраняются. Для компактного однострочного вывода опустите indent (или передайте None) и установите separators=(',', ':').

Сериализация пользовательских объектов Python с помощью параметра default

Стандартный модуль json сериализует словари, списки, строки, числа, булевы значения и None — но выбрасываетTypeError для любого другого типа. Два наиболее частых виновника в продакшн-коде — datetime-объекты и UUID.

Python 3.8+ — TypeError без обработки пользовательских типов
import json
from datetime import datetime, timezone
import uuid

order = {
    "order_id": uuid.uuid4(),            # ❌ TypeError: UUID is not JSON serializable
    "placed_at": datetime.now(timezone.utc),  # ❌ TypeError: datetime is not JSON serializable
    "total_usd": 142.50,
    "items": ["pro-subscription", "addon-storage"]
}

json.dumps(order)  # raises TypeError

Подход 1 — параметр default=

Передайте вызываемый объект в default=. json.dumps() вызывает его для любого объекта, который не может обработать. Верните сериализуемое представление или выбросьте TypeError для типов, которые вы явно не поддерживаете — никогда не игнорируйте неизвестные типы молча.

Python 3.8+
import json
from datetime import datetime, timezone, date
import uuid
from decimal import Decimal

def json_default(obj):
    if isinstance(obj, (datetime, date)):
        return obj.isoformat()
    if isinstance(obj, uuid.UUID):
        return str(obj)
    if isinstance(obj, Decimal):
        return float(obj)
    raise TypeError(f"Type {type(obj).__name__!r} is not JSON serializable")

order = {
    "order_id": uuid.uuid4(),
    "placed_at": datetime(2024, 5, 1, 10, 30, 0, tzinfo=timezone.utc),
    "total_usd": Decimal("142.50"),
    "items": ["pro-subscription", "addon-storage"]
}

print(json.dumps(order, indent=4, default=json_default))
# {
#     "order_id": "a3f1c2d4-e5b6-7890-abcd-ef1234567890",
#     "placed_at": "2024-05-01T10:30:00+00:00",
#     "total_usd": 142.5,
#     "items": ["pro-subscription", "addon-storage"]
# }

Подход 2 — создание подкласса json.JSONEncoder

Для переиспользуемой логики кодирования, общей для нескольких модулей, создание подкласса json.JSONEncoder чище, чем передача функции default повсюду. Переопределите метод default и вызывайте super().default(obj) в качестве последнего запасного варианта — это сохраняет корректное поведение ошибок для неподдерживаемых типов.

Python 3.8+
import json
from datetime import datetime, timezone
import uuid
from decimal import Decimal

class AppEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        if isinstance(obj, uuid.UUID):
            return str(obj)
        if isinstance(obj, Decimal):
            return float(obj)
        return super().default(obj)  # raises TypeError for unknown types

order = {
    "order_id": uuid.uuid4(),
    "placed_at": datetime(2024, 5, 1, 10, 30, 0, tzinfo=timezone.utc),
    "total_usd": Decimal("142.50"),
}

# Передайте класс энкодера через cls=
print(json.dumps(order, indent=4, cls=AppEncoder))
# Вывод идентичен подходу с default=
Примечание:Всегда вызывайте super().default(obj) (или явно выбрасывайте TypeError) для нераспознанных типов. Молчаливый возврат str(obj) для всего испортит объекты, которые должны были вызвать ошибку — такой баг сложно отследить в продакшне.

Обратное декодирование — object_hook

Кодирование — лишь половина истории. Чтобы восстановить пользовательский Python-объект из JSON, передайте функцию object_hook в json.loads() или json.load(). Хук вызывается для каждого декодированного JSON-объекта (словаря) и может вернуть любое Python-значение вместо него — обеспечивая полный цикл кодирование ↔ декодирование.

Python 3.8+
import json
from datetime import datetime
from dataclasses import dataclass

@dataclass
class Event:
    name: str
    occurred_at: datetime
    user_id: str

def encode_event(obj):
    if isinstance(obj, Event):
        return {
            "__type__": "Event",
            "name": obj.name,
            "occurred_at": obj.occurred_at.isoformat(),
            "user_id": obj.user_id,
        }
    raise TypeError(f"Cannot serialize {type(obj)}")

def decode_event(d):
    if d.get("__type__") == "Event":
        return Event(
            name=d["name"],
            occurred_at=datetime.fromisoformat(d["occurred_at"]),
            user_id=d["user_id"],
        )
    return d

# Кодирование
event = Event("login", datetime(2024, 5, 1, 10, 30), "usr_9f3a2b")
json_str = json.dumps(event, default=encode_event, indent=4)

# Декодирование обратно в экземпляр Event
restored = json.loads(json_str, object_hook=decode_event)
print(type(restored))           # <class 'Event'>
print(restored.occurred_at)     # 2024-05-01 10:30:00
Примечание:object_hook вызывается для каждого вложенного словаря в документе — не только для верхнего уровня. Включите поле-дискриминатор (например, "__type__"), чтобы хук мог отличить ваши пользовательские объекты от обычных словарей, которые следует оставить как есть.

pprint — альтернативный модуль (и когда его не использовать)

Модуль Python pprint (pretty printer) форматирует структуры данных Python для удобного чтения в терминале. Он работает с разобранными Python-объектами, а не с JSON-строками — и его вывод использует Python-синтаксис, а не JSON-синтаксис.

Python 3.8+
import json, pprint

raw = '{"sensor_id":"s-441","readings":[23.1,23.4,22.9],"unit":"celsius","active":true}'
data = json.loads(raw)

# pprint — валидный Python repr, НЕ валидный JSON
pprint.pprint(data, sort_dicts=False)
# {'sensor_id': 's-441',
#  'readings': [23.1, 23.4, 22.9],
#  'unit': 'celsius',
#  'active': True}        ← Python True, не JSON true

# json.dumps — валидный JSON
print(json.dumps(data, indent=4))
# {
#     "sensor_id": "s-441",
#     "readings": [23.1, 23.4, 22.9],
#     "unit": "celsius",
#     "active": true      ← валидный JSON
# }
Внимание:Никогда не отправляйте вывод pprint в API-эндпоинт и не записывайте его в .json-файл — это сломает любой JSON-парсер, ожидающий стандартный синтаксис. Используйте json.dumps(indent=4) для любого вывода, который должен быть валидным JSON.

Когда pprint уместен: быстрый просмотр Python-объектов в REPL или отладочном логе, особенно когда объект содержит типы, не сериализуемые в JSON (множества, экземпляры пользовательских классов, dataclass-объекты до конвертации).

Как форматировать JSON-ответ из requests

Самый распространённый реальный сценарий: у вас есть JSON-файл на диске или HTTP-ответ от API, и вы хотите отформатировать его для отладки или логирования. В обоих случаях подход одинаков — разобрать в словарь Python, затем отформатировать через json.dumps().

Чтение из файла

Python 3.8+
import json

try:
    with open("config.json", "r", encoding="utf-8") as f:
        data = json.load(f)

    # Форматированный вывод в консоль
    print(json.dumps(data, indent=4, ensure_ascii=False))

    # Или записать форматированную версию обратно на диск
    with open("config.pretty.json", "w", encoding="utf-8") as f:
        json.dump(data, f, indent=4, ensure_ascii=False)

except json.JSONDecodeError as e:
    print(f"Invalid JSON: {e}")
except FileNotFoundError:
    print(f"File not found: config.json")

Форматирование API-ответа

Python 3.8+ (requires: pip install requests)
import json, requests
from requests.exceptions import HTTPError, ConnectionError, Timeout

def pretty_print_api(url: str) -> None:
    try:
        resp = requests.get(url, timeout=10)
        resp.raise_for_status()
        print(json.dumps(resp.json(), indent=4, ensure_ascii=False))
    except HTTPError as e:
        print(f"HTTP {e.response.status_code}: {e}")
    except (ConnectionError, Timeout) as e:
        print(f"Network error: {e}")
    except json.JSONDecodeError:
        print(f"Response body is not JSON:\n{resp.text[:500]}")

pretty_print_api("https://api.github.com/repos/python/cpython")
Примечание:response.json() уже разбирает тело ответа — вызывать json.loads() отдельно не нужно. Всегда добавляйте raise_for_status() перед обращением к .json(), чтобы перехватывать ошибки 4xx/5xx раньше, чем они вызовут непонятную ошибку разбора.

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

Python поставляется с json.tool — CLI-модулем для форматирования JSON прямо из терминала, без написания Python-скрипта. Доступен на любой машине с установленным Python.

bash
# Форматировать локальный файл
python -m json.tool config.json

# Передать API-ответ через форматтер
curl -s https://api.github.com/users/gvanrossum | python -m json.tool

# Форматировать из stdin
echo '{"service":"api-gateway","version":"2.1.0","healthy":true}' | python -m json.tool

# Отсортировать ключи по алфавиту
python -m json.tool --sort-keys data.json

# Пользовательский отступ (Python 3.9+)
python -m json.tool --indent 2 data.json
Примечание:Python 3.9 добавил флаги --indent и --no-indent. Для более мощной фильтрации JSON в терминале рассмотрите jq — но python -m json.tool покрывает задачу форматирования без дополнительных зависимостей.

Если вы вообще не в терминале — вставляете ответ из Postman или лог-файл — JSON Formatter от ToolDeck позволяет вставить, отформатировать и скопировать за один шаг со встроенной подсветкой синтаксиса и валидацией.

Альтернативные библиотеки: orjson и rich

orjson — в 5–10× быстрее с нативной поддержкой типов

Стандартного модуля json достаточно для большинства случаев, но если вы сериализуете тысячи объектов в секунду — в пайплайнах логирования, высоконагруженных API, при больших экспортах данных — orjson работает в 5–10× быстрее. Он также нативно поддерживает типы, которые стандартная библиотека не может сериализовать без пользовательской функции default: datetime, uuid.UUID, массивы numpy и dataclass-объекты.

bash — установка
pip install orjson
Python 3.8+
import orjson
from datetime import datetime, timezone
import uuid

event = {
    "event_id": uuid.uuid4(),                  # str() не нужен — orjson поддерживает UUID
    "timestamp": datetime.now(timezone.utc),   # isoformat() не нужен
    "service": "auth-service",
    "level": "INFO",
    "payload": {
        "user_id": "usr_9f3a2b",
        "action": "login",
        "ip": "192.168.1.42",
        "latency_ms": 34
    }
}

# orjson.dumps возвращает bytes; .decode() конвертирует в str
print(orjson.dumps(event, option=orjson.OPT_INDENT_2).decode())
# {
#   "event_id": "a3f1c2d4-e5b6-7890-abcd-ef1234567890",
#   "timestamp": "2024-05-01T10:30:00+00:00",
#   "service": "auth-service",
#   ...
# }

Два важных момента: orjson.dumps() возвращает bytes, а не строку — вызовите .decode() если нужна строка. Он поддерживает только 2-пробельный отступ через OPT_INDENT_2; для 4-пробельного вывода используйте стандартный json.dumps(indent=4).

rich — подсветка синтаксиса в терминале

Если вы регулярно просматриваете JSON в терминале или REPL, rich отображает цветной синтаксически подсвеченный вывод, делающий глубоко вложенные структуры читаемыми с первого взгляда. Ключи, строки, числа и булевы значения получают разные цвета — гораздо удобнее для просмотра, чем монохромный текст. Это инструмент только для отладки, а не для продакшн-сериализации.

bash — установка
pip install rich
Python 3.8+
from rich import print_json
import json

# print_json() принимает JSON-строку
raw = '{"event":"login","user_id":"usr_9f3a2b","timestamp":"2024-05-01T10:30:00Z","success":true,"meta":{"ip":"192.168.1.42","attempts":1}}'
print_json(raw)

# Для форматирования Python-словаря сначала конвертируйте в строку
data = {
    "status": "success",
    "count": 42,
    "tags": ["python", "api", "backend"]
}
print_json(json.dumps(data))
Внимание:rich.print_json() выводит ANSI escape-коды для цвета терминала — никогда не захватывайте этот вывод и не записывайте его в .json-файл и не отправляйте как API-ответ. Используйте json.dumps(indent=4) для любого машиночитаемого вывода.

simplejson — совместимая замена stdlib

simplejson — библиотека, ставшая стандартным модулем json Python — она по-прежнему поддерживается независимо и опережает stdlib в ряде функций. Это настоящая замена без изменения кода: замените импорт, и остальной код остаётся прежним. Полезна, когда нужна поддержка Decimal без пользовательского энкодера или при работе со старыми окружениями Python.

bash — установка
pip install simplejson
Python 3.8+
import simplejson as json  # identical API to the stdlib
from decimal import Decimal

order = {
    "item": "API subscription",
    "price": Decimal("49.99"),   # stdlib json raises TypeError here
    "quantity": 3,
}

# simplejson сериализует Decimal нативно — default= не нужен
print(json.dumps(order, indent=4, use_decimal=True))
# {
#     "item": "API subscription",
#     "price": 49.99,
#     "quantity": 3
# }
Примечание:Для чистой производительности orjson — лучший выбор. Обращайтесь к simplejson, когда нужна нативная сериализация Decimal без написания пользовательского энкодера, или при работе с кодовой базой, которая уже его использует.

Обработка больших JSON-файлов без нехватки памяти

json.load() читает весь файл в память, прежде чем вы сможете получить доступ к одному полю. На файле с миллионами записей или payload объёмом более гигабайта это вызывает MemoryError — или в лучшем случае заставляет процесс уходить в swap и замедляться.

Потоковая обработка с ijson

ijson — потоковый JSON-парсер, генерирующий элементы по одному из файлового объекта. Вы итерируетесь по элементам массива, не удерживая весь датасет в памяти — пиковое потребление памяти пропорционально одному объекту, а не размеру файла.

bash — установка
pip install ijson
Python 3.8+
import ijson
from decimal import Decimal

# events.json структура: {"events": [...миллионы объектов...]}
total_revenue = Decimal("0")
login_count = 0

with open("events.json", "rb") as f:   # ijson требует бинарный режим
    for event in ijson.items(f, "events.item"):
        if event.get("type") == "purchase":
            total_revenue += Decimal(str(event["amount_usd"]))
        elif event.get("type") == "login":
            login_count += 1

print(f"Revenue: ${total_revenue:.2f}  |  Logins: {login_count}")
# Обрабатывает файл 2 ГБ при ~30 МБ пикового потребления памяти
Примечание:Переключайтесь с json.load() на ijson, когда файл превышает примерно 50–100 МБ. Ниже этого порога json.load() проще и значительно быстрее, так как использует внутренний C-extension парсер. Выше 100 МБ экономия памяти от потоковой обработки перевешивает дополнительные накладные расходы.

NDJSON — один JSON-объект на строку

NDJSON (Newline Delimited JSON, также называемый JSON Lines или .jsonl) хранит один полный JSON-объект на строку. Экспортёры логов, Kafka-консьюмеры и пайплайны данных часто используют этот формат, потому что каждую строку можно дописывать и читать независимо — не нужно разбирать весь файл для добавления записи. Стандартная библиотека обрабатывает его без дополнительных зависимостей.

Python 3.8+
import json
from pathlib import Path

# Запись NDJSON — одно событие на строку
events = [
    {"ts": "2024-05-01T10:00:00Z", "user": "usr_9f3a2b", "action": "login"},
    {"ts": "2024-05-01T10:01:03Z", "user": "usr_9f3a2b", "action": "purchase", "sku": "pro-plan"},
    {"ts": "2024-05-01T10:15:42Z", "user": "usr_4ab1d9", "action": "login"},
]

with open("events.ndjson", "w", encoding="utf-8") as f:
    for event in events:
        f.write(json.dumps(event, ensure_ascii=False) + "\n")

# Чтение NDJSON — постоянное потребление памяти, независимо от размера файла
purchase_count = 0
with open("events.ndjson", "r", encoding="utf-8") as f:
    for line in f:
        line = line.strip()
        if not line:           # пропустить пустые строки
            continue
        event = json.loads(line)
        if event.get("action") == "purchase":
            purchase_count += 1
            print(f"{event['ts']} — {event['user']} bought {event['sku']}")

Распространённые ошибки

Я видел эти четыре ошибки почти в каждом code review, связанном с сериализацией JSON — особенно у разработчиков, пришедших из JavaScript, где JSON.stringify обрабатывает кодирование автоматически.

Использование print(data) вместо json.dumps()

Проблема: print() на словаре использует Python repr — вывод показывает True/None (синтаксис Python), а не true/null (синтаксис JSON). Это не валидный JSON.

Решение: Всегда используйте json.dumps(data, indent=4) для валидного читаемого JSON-вывода.

Before · Python
After · Python
data = {"active": True, "count": None}
print(data)
# {'active': True, 'count': None}
print(json.dumps(data, indent=4))
# {
#     "active": true,
#     "count": null
# }
Забытый ensure_ascii=False с не-ASCII текстом

Проблема: Специальные символы (буквы с диакритикой, кириллица, CJK, emoji) экранируются в последовательности \\uXXXX, делая вывод нечитаемым.

Решение: Передайте ensure_ascii=False для сохранения исходных Unicode-символов.

Before · Python
After · Python
user = {"name": "Иван Петров"}
json.dumps(user, indent=2)
# {"name": "\u0418\u0432\u0430\u043d \u041f\u0435\u0442\u0440\u043e\u0432"}
json.dumps(user, indent=2, ensure_ascii=False)
# {"name": "Иван Петров"}
Использование json.dumps() для записи в файл

Проблема: json.dumps() возвращает строку; после этого нужен отдельный вызов f.write(), создающий лишнюю промежуточную строку.

Решение: Используйте json.dump(data, f, indent=4) — записывает напрямую в файловый объект.

Before · Python
After · Python
with open("out.json", "w") as f:
    f.write(json.dumps(data, indent=4))
with open("out.json", "w", encoding="utf-8") as f:
    json.dump(data, f, indent=4, ensure_ascii=False)
Форматирование через pprint в ожидании валидного JSON

Проблема: pprint.pprint() использует Python-синтаксис (True, None, одинарные кавычки), который JSON-парсеры отвергают.

Решение: Используйте json.dumps(indent=4) для любого вывода, который должен разбираться как JSON.

Before · Python
After · Python
import pprint
pprint.pprint({"running": True, "last_error": None})
# {'running': True, 'last_error': None}
import json
print(json.dumps({"running": True, "last_error": None}, indent=4))
# {"running": true, "last_error": null}

Сравнение методов — json.dumps, orjson, simplejson, rich

Используйте json.dumps() для повседневного форматирования и записи в файлы — он покрывает 95% случаев без зависимостей. Обращайтесь к orjson при сериализации на горячем пути или когда объекты включают поля datetime и UUID. Используйте simplejson когда нужна совместимость со stdlib и нативная поддержка Decimal из коробки. Оставьте rich.print_json() и pprint исключительно для локального просмотра в терминале — ни тот, ни другой не дают машиночитаемый вывод.

Метод
Вывод
Валидный JSON
Скорость
Non-ASCII
Свои типы
Установка
json.dumps(indent=4)
String
Стандарт
ensure_ascii=False
default= / JSONEncoder
Встроен
json.dump(f, indent=4)
Файл
Стандарт
ensure_ascii=False
default= / JSONEncoder
Встроен
pprint.pprint()
Python repr
Стандарт
Нативно
✅ (любой repr)
Встроен
orjson.dumps(OPT_INDENT_2)
Bytes
в 5–10× быстрее
Нативно
datetime, UUID, numpy
pip install orjson
python -m json.tool
CLI stdout
Стандарт
Встроен
simplejson.dumps()
String
~1.5× быстрее
ensure_ascii=False
Decimal нативно
pip install simplejson
rich.print_json()
Только терминал
✅ (вход)
Стандарт
pip install rich

Часто задаваемые вопросы

Как отформатировать JSON в Python с отступами?

Вызовите json.dumps(data, indent=4). Параметр indent задаёт количество пробелов на каждый уровень вложенности. Сначала импортируйте модуль json — он входит в стандартную библиотеку Python, никакой установки через pip не требуется. Передайте ensure_ascii=False, если данные содержат не-ASCII символы: буквы с диакритикой, кириллицу, символы CJK.

python
import json

user = {"username": "ipetrov", "plan": "enterprise", "permissions": ["read", "write", "deploy"]}
print(json.dumps(user, indent=4))

В чём разница между json.dumps() и json.dump()?

json.dumps() (с буквой "s") возвращает отформатированную строку в памяти. json.dump() (без "s") записывает непосредственно в файлоподобный объект — передайте открытый файловый дескриптор вторым аргументом. Для записи форматированного JSON на диск json.dump(data, f, indent=4) является идиоматическим подходом и не создаёт промежуточную строку в памяти.

python
# dumps → строка в памяти
formatted = json.dumps(data, indent=4)

# dump → запись напрямую в файл
with open('output.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, indent=4)

Почему json.dumps() показывает \u0441\u0442\u0440 вместо реальных символов?

По умолчанию ensure_ascii=True экранирует каждый не-ASCII символ в последовательность \uXXXX. Передайте ensure_ascii=False, чтобы сохранить исходные Unicode-символы. Особенно важно при работе с именами, адресами и любым пользовательским контентом на нелатинских алфавитах.

python
data = {"city": "Москва", "greeting": "你好"}

# По умолчанию — экранировано
json.dumps(data, indent=4)
# {"city": "\u041c\u043e\u0441\u043a\u0432\u0430", ...}

# Читаемо
json.dumps(data, indent=4, ensure_ascii=False)
# {"city": "Москва", "greeting": "你好"}

Как отформатировать JSON-строку (не словарь)?

Сначала разберите строку с помощью json.loads(), затем отформатируйте через json.dumps(). Оба вызова можно объединить в одну строку для быстрого просмотра в терминале.

python
import json

raw = '{"endpoint":"/api/v2/users","timeout":30,"retry":true}'
print(json.dumps(json.loads(raw), indent=4))

Можно ли использовать pprint для форматирования JSON в Python?

pprint.pprint() выводит Python-представление объекта, а не валидный JSON. Он использует True/False/None (синтаксис Python), а не true/false/null (синтаксис JSON). Никогда не передавайте вывод pprint в API или JSON-парсер — используйте json.dumps(indent=4) для всего, что должно быть валидным JSON.

python
import pprint, json

data = {"active": True, "score": None}

pprint.pprint(data)     # {'active': True, 'score': None}  ← не JSON
json.dumps(data, indent=4)  # {"active": true, "score": null}  ← валидный JSON

Как отсортировать ключи JSON в алфавитном порядке в Python?

Добавьте sort_keys=True в json.dumps(). Для командной строки используйте python -m json.tool --sort-keys data.json. Отсортированные ключи делают JSON-дифы читаемыми и помогают сразу замечать изменённые значения.

python
import json

server = {"workers": 4, "host": "0.0.0.0", "port": 8080, "debug": False}
print(json.dumps(server, indent=4, sort_keys=True))
# {
#     "debug": false,
#     "host": "0.0.0.0",
#     "port": 8080,
#     "workers": 4
# }

Python даёт полный контроль — кастомные сериализаторы, стриминг, интеграция в пайплайны. Когда нужно просто проверить или поделиться отформатированным фрагментом, JSON Formatter от ToolDeck — более быстрый путь: вставьте JSON и получите результат с отступами и подсветкой без настройки окружения.

Похожие инструменты

Также доступно на:GoJavaScriptBash
MS
Maria SantosBackend Developer

Maria is a backend developer specialising in Python and API integration. She has broad experience with data pipelines, serialisation formats, and building reliable server-side services. She is an active member of the Python community and enjoys writing practical, example-driven guides that help developers solve real problems without unnecessary theory.

DV
Dmitri VolkovТехнический рецензент

Dmitri is a DevOps engineer who relies on Python as his primary scripting and automation language. He builds internal tooling, CI/CD pipelines, and infrastructure automation scripts that run in production across distributed teams. He writes about the Python standard library, subprocess management, file processing, encoding utilities, and the practical shell-adjacent Python that DevOps engineers use every day.