Format JSON in Python: pprint, json.dumps, and the indent trap
Formatting JSON in Python is a one-liner that everyone gets subtly wrong. The standard library is enough, but pprint is not the answer and indent=4 is a habit, not a decision.
The correct one-liner
Use json.dumps from the standard library. Always. The two arguments that matter are indent and sort_keys.
indent=2 is the modern default and matches what every JS tooling produces. indent=4 is a Python tradition from PEP 8, but PEP 8 is about Python source, not JSON. Mixing the two creates noisy diffs whenever a JS dev opens your file. Pick indent=2 and stop thinking about it.
sort_keys=True is the difference between a pretty file and a deterministic file. If two services emit the same JSON in different key orders, your diff tool will scream and your tests will flake. Sorting fixes both.
Why pprint is the wrong tool
pprint.pprint is for Python objects, not JSON. It will happily print {'a': True} with single quotes and True instead of true, which is not valid JSON. The output looks similar at a glance, breaks every JSON parser on the planet at parse time.
If you need a Python-readable repr, pprint is fine. If you need JSON, use json.dumps. They are different tools.
Streaming and large payloads
json.dumps builds the full string in memory. For multi-gigabyte payloads use json.dump with a file handle to write incrementally:
with open("out.json", "w") as f:
json.dump(huge_object, f, indent=2, sort_keys=True)
For genuinely streaming JSON (where you do not control the structure) reach for ijson or orjson. orjson is also 2 to 3 times faster than the stdlib for normal sizes.
When to skip Python entirely
If you want a quick visual format of a payload you are debugging, opening the terminal, importing json, and pasting the string is six steps too many. Paste it into a browser tool that runs locally and never touches a server, and you save a minute.
Working example
pythonimport json
data = {
"user": {"id": 42, "name": "Ada"},
"tags": ["admin", "beta"],
"active": True,
}
# Pretty, deterministic, valid JSON
formatted = json.dumps(data, indent=2, sort_keys=True)
print(formatted)
# Streaming write for large payloads
with open("out.json", "w") as f:
json.dump(data, f, indent=2, sort_keys=True) Just need the result?
When you just want to inspect a payload visually without touching a terminal, paste it into the browser-based formatter and see the result with one click. Zero install, zero upload, valid JSON every time.
Open JSON Formatter and Validator →Frequently asked questions
Does json.dumps preserve key order by default?
Yes since Python 3.7. The dict keeps insertion order and json.dumps respects it. Use sort_keys=True only when you want alphabetical order for diffs.
How do I handle non-serialisable types like datetime?
Pass a default callable: json.dumps(obj, default=str) coerces datetime, Decimal, UUID and similar to their string repr. Cleaner than custom encoders for one-off scripts.
Why does my output have escaped Unicode like \u00e9?
json.dumps defaults to ensure_ascii=True. Pass ensure_ascii=False if you want literal accented characters. The output stays valid JSON as long as you save the file as UTF-8.