Python has excellent JSON support built into the standard library. Most use cases need nothing more than json.dumps with an indent argument. But for command-line use, color output, or maximum speed, there are better options.
Method 1: json.dumps (the obvious one)
The standard library does the job for nearly every case:
import json
data = {"users": [{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}]}
print(json.dumps(data, indent=2))
Output:
{
"users": [
{
"name": "Alice",
"age": 30
},
{
"name": "Bob",
"age": 25
}
]
}
Useful parameters:
indent=2— most common; 2-space indentation.indent=4— wider, more readable for deeply nested data.indent="\t"— tab indentation if you prefer.sort_keys=True— sort object keys alphabetically (useful for deterministic output).ensure_ascii=False— keep non-ASCII characters as-is rather than escaping (e.g.,éinstead of\u00e9).separators=(",", ": ")— control spacing around separators.
Method 2: command-line one-liner
When you have a JSON file to format quickly:
python -m json.tool input.json
# Or with explicit indent:
python -m json.tool --indent 2 input.json
This reads the file (or stdin) and writes formatted JSON to stdout. Useful in shell pipelines:
curl https://api.example.com/data | python -m json.tool
Method 3: rich for colored output
For terminal output with syntax highlighting, the rich library is excellent:
from rich import print_json
data = {"users": [{"name": "Alice", "age": 30}]}
print_json(data=data)
Output gets full color terminal highlighting — keys in one color, strings in another, numbers in another. Great for debugging and CLI tools where readability matters.
Method 4: orjson for speed
If you're formatting megabytes of JSON regularly, orjson is dramatically faster than the standard library:
import orjson
data = {"users": [{"name": "Alice", "age": 30}]}
formatted = orjson.dumps(data, option=orjson.OPT_INDENT_2)
print(formatted.decode())
orjson is 2-5x faster than the standard library for serialization. It also handles dataclasses, datetimes, and numpy arrays natively. The trade-off: it returns bytes (not strings), and the indentation options are less flexible — only 2-space indent is supported.
Handling special types
The standard library can't serialize datetime, Decimal, or custom classes by default. Pass a custom encoder:
import json
from datetime import datetime
from decimal import Decimal
class CustomEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
if isinstance(obj, Decimal):
return str(obj)
return super().default(obj)
print(json.dumps(data, indent=2, cls=CustomEncoder))
Reading JSON files
The mirror image of json.dumps:
with open("data.json") as f:
data = json.load(f)
# Or from a string:
data = json.loads(json_string)
Both raise json.JSONDecodeError on invalid JSON, with line and column information in the error message.
Formatting JSON in pandas DataFrames
If your JSON comes from a DataFrame, both directions:
import pandas as pd
# DataFrame → pretty JSON
df.to_json(orient="records", indent=2)
# JSON → DataFrame
df = pd.read_json("data.json")
Common pitfalls
NaN, Infinity, -Infinity. These are Python floats but invalid JSON. json.dumps emits them by default (technically invalid), but with allow_nan=False it raises an error. Decide which behavior you want explicitly.
Tuple vs list. Python tuples serialize as JSON arrays, same as lists. But deserialization always returns lists — round-trip changes tuples to lists. If type fidelity matters, convert before serializing.
Set serialization. Sets aren't JSON-serializable. Convert to a list first: json.dumps(list(my_set)).
None vs null. Python's None serializes as JSON's null. This is symmetric and works as expected.
Validating before formatting
If you receive JSON from an external source, validate before formatting to surface issues with a clear error:
import json
def safe_format(text):
try:
data = json.loads(text)
return json.dumps(data, indent=2)
except json.JSONDecodeError as e:
return f"Invalid JSON at line {e.lineno}, col {e.colno}: {e.msg}"
For one-off formatting, our tool
If you don't want to write code, our JSON Formatter does the same thing entirely in the browser. Paste JSON, get formatted output, copy or download. Useful for inspecting API responses without leaving the browser.
Wrap-up
For 95% of cases, json.dumps(data, indent=2) is all you need. Use python -m json.tool for command-line work. Reach for rich when you want colored terminal output, or orjson when speed matters.