Home / Blog / How to Format JSON in Python

How to Format JSON in Python: Complete Guide 2026

Last updated: May 16, 2026 · 10 min read

Formatting JSON in Python is one of the most common tasks developers face daily. Whether you're debugging API responses, saving configuration files, or generating readable data exports, Python's built-in json module makes it straightforward. This guide covers everything from basic pretty printing to advanced custom encoders.

Quick Tip: Need to format JSON right now without writing code? Try our free Online JSON Formatter — paste your JSON and get perfectly formatted output instantly.

Basic JSON Formatting with json.dumps

The simplest way to format JSON in Python is using json.dumps() with the indent parameter. This function converts a Python object to a JSON-formatted string.

import json

data = {
    "name": "Alice",
    "age": 30,
    "skills": ["Python", "JavaScript", "Go"],
    "address": {
        "city": "Shanghai",
        "country": "China"
    }
}

# Pretty print with 2-space indentation
formatted = json.dumps(data, indent=2)
print(formatted)

The output will be a nicely formatted JSON string:

{
  "name": "Alice",
  "age": 30,
  "skills": [
    "Python",
    "JavaScript",
    "Go"
  ],
  "address": {
    "city": "Shanghai",
    "country": "China"
  }
}

Understanding the indent Parameter

The indent parameter controls the number of spaces used for each level of nesting. Common values are:

# Compact (default)
json.dumps(data)
# '{"name": "Alice", "age": 30, ...}'

# Tab indentation
json.dumps(data, indent='\t')
# '{\n\t"name": "Alice",\n\t"age": 30,\n\t...
'

Sorting Keys with sort_keys

For consistent, deterministic output — especially useful in testing and version control — use the sort_keys parameter:

formatted = json.dumps(data, indent=2, sort_keys=True)
print(formatted)

This sorts all keys alphabetically at every level of nesting, making it easier to compare JSON outputs across runs.

Writing JSON to a File with json.dump

While json.dumps() returns a string, json.dump() writes directly to a file object. This is more memory-efficient for large datasets:

import json

data = {
    "users": [
        {"id": 1, "name": "Bob"},
        {"id": 2, "name": "Charlie"}
    ],
    "total": 2
}

# Write formatted JSON to file
with open("output.json", "w", encoding="utf-8") as f:
    json.dump(data, f, indent=2, ensure_ascii=False)

print("JSON written to output.json")

Important: Always use ensure_ascii=False when your data contains non-ASCII characters (Chinese, Japanese, emojis, etc.). Without it, characters like 你好 will be escaped as \u4f60\u597d.

Handling Non-Serializable Types

Python's json module can only serialize basic types: str, int, float, bool, None, list, and dict. For other types, you need a custom encoder.

Handling datetime Objects

This is the most common case. Python's datetime objects aren't JSON-serializable by default:

import json
from datetime import datetime, date

class DateTimeEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        if isinstance(obj, date):
            return obj.isoformat()
        return super().default(obj)

data = {
    "event": "Python Conference",
    "date": datetime(2026, 6, 15, 9, 0),
    "created": date(2026, 1, 1)
}

formatted = json.dumps(data, indent=2, cls=DateTimeEncoder)
print(formatted)

Output:

{
  "event": "Python Conference",
  "date": "2026-06-15T09:00:00",
  "created": "2026-01-01"
}

Handling Decimal and Other Numeric Types

import json
from decimal import Decimal

class SmartEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Decimal):
            return float(obj)
        if isinstance(obj, set):
            return list(obj)
        if isinstance(obj, bytes):
            return obj.decode("utf-8")
        return super().default(obj)

data = {
    "price": Decimal("19.99"),
    "tags": {"python", "json", "tutorial"},
    "content": b"Hello World"
}

print(json.dumps(data, indent=2, cls=SmartEncoder))

Using the default Parameter (Simpler Approach)

For one-off cases, you can pass a function directly to the default parameter instead of creating a full encoder class:

import json
from datetime import datetime

def serialize(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    raise TypeError(f"Type {type(obj)} not serializable")

data = {"timestamp": datetime.now()}
print(json.dumps(data, default=serialize))

Controlling Output Format

Custom Separators

The separators parameter lets you control the separator between items. The default is (', ', ': ') for pretty output. For compact output matching JavaScript's JSON.stringify:

# Compact like JavaScript's JSON.stringify
compact = json.dumps(data, separators=(',', ':'))
# '{"name":"Alice","age":30}'

# Custom separators
custom = json.dumps(data, separators=(' | ', ' = '))
# '{"name" = "Alice" | "age" = 30}'

Handling Non-ASCII Characters

data = {"greeting": "你好世界", "emoji": "🐍"}

# Default: escapes non-ASCII
print(json.dumps(data))
# {"greeting": "\u4f60\u597d\u4e16\u754c", "emoji": "\ud83d\udc0d"}

# With ensure_ascii=False: preserves Unicode
print(json.dumps(data, ensure_ascii=False, indent=2))
# {
#   "greeting": "你好世界",
#   "emoji": "🐍"
# }

Reading and Formatting Existing JSON Files

A common workflow is reading a JSON file, possibly modifying it, and writing it back in a formatted way:

import json

# Read, format, and rewrite
with open("config.json", "r", encoding="utf-8") as f:
    data = json.load(f)

# Optionally modify the data
data["last_modified"] = "2026-05-16"

# Write back with formatting
with open("config.json", "w", encoding="utf-8") as f:
    json.dump(data, f, indent=2, ensure_ascii=False, sort_keys=True)

Advanced: Pretty Print JSON from a String

If you already have a JSON string (e.g., from an API response) and want to format it:

import json

raw_json = '{"name":"Alice","age":30,"skills":["Python","JS"]}'

# Parse and re-format
parsed = json.loads(raw_json)
formatted = json.dumps(parsed, indent=2)
print(formatted)

Format JSON from Command Line

You can use Python as a quick JSON formatter from the terminal:

# Format a JSON file
python -m json.tool input.json

# Format and save
python -m json.tool input.json > formatted.json

# Format from a pipe
echo '{"a":1,"b":2}' | python -m json.tool

# With indentation
python -m json.tool --indent 4 input.json

# Sort keys
python -m json.tool --sort-keys input.json

Performance Considerations

For large JSON files, keep these tips in mind:

Comparison: json.dumps vs json.dump

import json

data = {"key": "value"}

# Returns string
json_string = json.dumps(data, indent=2)

# Writes to file
with open("out.json", "w") as f:
    json.dump(data, f, indent=2)

Common json.dumps Parameters Reference

Frequently Asked Questions

How do I pretty print JSON in Python?

Use json.dumps(data, indent=2) to get a formatted JSON string. For printing to console, you can also use pprint module, but json.dumps with indent gives proper JSON formatting.

What is the difference between json.dumps and json.dump?

json.dumps() returns a JSON-formatted string. json.dump() writes JSON directly to a file object. Use dumps when you need a string, dump when writing to a file.

How do I format JSON with 4 spaces in Python?

Pass indent=4 to json.dumps(): json.dumps(data, indent=4).

How do I handle datetime objects in JSON?

Create a custom encoder class that inherits from json.JSONEncoder and override the default method to convert datetime objects to ISO format strings. Pass it as cls=YourEncoder to json.dumps().

Why are my Chinese/Unicode characters escaped in JSON output?

By default, json.dumps sets ensure_ascii=True, which escapes non-ASCII characters. Pass ensure_ascii=False to preserve them.

How do I format JSON from the command line?

Use Python's built-in module: python -m json.tool input.json. Add --sort-keys for sorted output and --indent 4 for custom indentation.

Try It Online

Don't want to write code just to format JSON? Use our free online JSON Formatter — paste your JSON, choose your indentation, and get formatted output instantly. No signup required.