DEV Community

楊東霖
楊東霖

Posted on • Originally published at devtoolkit.cc

How to Parse and Format JSON in Python: Complete Guide

Knowing how to parse JSON in Python is a core skill — Python's built-in json module handles virtually every use case without any third-party dependencies. Whether you're reading API responses, loading configuration files, or transforming data between services, this guide covers everything from basic parsing to error handling, pretty printing, nested objects, and custom serialization of types the json module does not support by default.

Basic Parsing with json.loads()

json.loads() (load string) parses a JSON string and returns a Python object:

import json

json_string = '{"name": "Alice", "age": 30, "active": true, "score": null}'

data = json.loads(json_string)
print(data)          # {'name': 'Alice', 'age': 30, 'active': True, 'score': None}
print(type(data))    # <class 'dict'>
print(data['name'])  # "Alice"
Enter fullscreen mode Exit fullscreen mode

JSON types map to Python types as follows:

  • objectdict
  • arraylist
  • stringstr
  • number (int)int
  • number (float)float
  • true / falseTrue / False
  • nullNone

Serializing Python Objects with json.dumps()

json.dumps() (dump string) converts a Python object to a JSON string:

import json

data = {
    "name": "Bob",
    "scores": [95, 87, 92],
    "metadata": {"active": True, "rank": None},
}

json_string = json.dumps(data)
print(json_string)
# '{"name": "Bob", "scores": [95, 87, 92], "metadata": {"active": true, "rank": null}}'
Enter fullscreen mode Exit fullscreen mode

Pretty Printing JSON

Use the indent parameter to produce human-readable output:

pretty = json.dumps(data, indent=2)
print(pretty)
# {
#   "name": "Bob",
#   "scores": [
#     95,
#     87,
#     92
#   ],
#   ...
# }

# Sort keys alphabetically
sorted_json = json.dumps(data, indent=2, sort_keys=True)

# Compact output (no spaces) for network transmission
compact = json.dumps(data, separators=(',', ':'))
Enter fullscreen mode Exit fullscreen mode

Reading and Writing JSON Files

Use json.load() and json.dump() (without the "s") when working with file objects:

import json

# Read JSON from a file
with open('config.json', 'r', encoding='utf-8') as f:
    config = json.load(f)

print(config['database']['host'])

# Write JSON to a file
with open('output.json', 'w', encoding='utf-8') as f:
    json.dump(config, f, indent=2, ensure_ascii=False)
    # ensure_ascii=False preserves Unicode characters (e.g., Chinese, emoji)
Enter fullscreen mode Exit fullscreen mode

Always specify encoding='utf-8' explicitly — the default encoding is platform-dependent and will cause problems on Windows if your JSON contains non-ASCII characters.

Error Handling

Parsing untrusted JSON without error handling will crash your program. Always wrap json.loads() in a try/except:

import json

def safe_parse(json_string):
    try:
        return json.loads(json_string)
    except json.JSONDecodeError as e:
        print(f"JSON parse error: {e.msg}")
        print(f"At line {e.lineno}, column {e.colno}")
        print(f"Document snippet: ...{e.doc[max(0, e.pos-20):e.pos+20]}...")
        return None

# JSONDecodeError attributes
result = safe_parse('{"bad": json}')
# JSON parse error: Expecting value
# At line 1, column 9
Enter fullscreen mode Exit fullscreen mode

json.JSONDecodeError is a subclass of ValueError, so you can also catch it with except ValueError for broader compatibility.

Working with Nested Objects

import json

api_response = '''
{
  "status": "ok",
  "users": [
    {"id": 1, "name": "Alice", "address": {"city": "Taipei", "zip": "100"}},
    {"id": 2, "name": "Bob",   "address": {"city": "Tokyo",  "zip": "100-0001"}}
  ]
}
'''

data = json.loads(api_response)

# Access nested values
for user in data['users']:
    print(f"{user['name']} lives in {user['address']['city']}")

# Safe access for optional keys
city = data.get('users', [{}])[0].get('address', {}).get('city', 'Unknown')
Enter fullscreen mode Exit fullscreen mode

Custom Serialization for Unsupported Types

By default, json.dumps() raises a TypeError for types it does not know about (datetime, Decimal, custom classes, etc.). Use a custom encoder:

import json
from datetime import datetime, date
from decimal import Decimal

class ExtendedEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, (datetime, date)):
            return obj.isoformat()
        if isinstance(obj, Decimal):
            return float(obj)
        if hasattr(obj, '__dict__'):
            return obj.__dict__
        return super().default(obj)

data = {
    "created_at": datetime.now(),
    "price": Decimal("9.99"),
}

print(json.dumps(data, cls=ExtendedEncoder, indent=2))
# {
#   "created_at": "2026-03-21T14:30:00.123456",
#   "price": 9.99
# }
Enter fullscreen mode Exit fullscreen mode

Parsing JSON from API Responses

import json
import urllib.request

def fetch_json(url):
    with urllib.request.urlopen(url) as response:
        raw = response.read().decode('utf-8')
        return json.loads(raw)

# With the requests library (more common in practice)
import requests

def fetch_json_requests(url):
    response = requests.get(url, timeout=10)
    response.raise_for_status()
    return response.json()  # requests calls json.loads() internally
Enter fullscreen mode Exit fullscreen mode

Performance Tips for Large JSON Files

  • Use json.load(file) (streaming from file) instead of reading the entire file into a string with read() first
  • For very large JSON files (hundreds of MB), consider ijson for streaming item-by-item parsing
  • For high-performance scenarios, the orjson library is a drop-in replacement that is 10–20x faster than the standard library
# orjson — fastest JSON library for Python
# pip install orjson
import orjson

data = orjson.loads(json_bytes)  # input can be bytes or str
json_bytes = orjson.dumps(data, option=orjson.OPT_INDENT_2)
Enter fullscreen mode Exit fullscreen mode

Quick Formatting During Development

When working with API responses or debugging, the JSON formatter tool lets you paste raw JSON and instantly view it pretty-printed and validated. See also the guide to JSON formatting and validation for a broader overview of JSON tooling.

Summary

  • Use json.loads() to parse a JSON string; json.load() to parse from a file object
  • Use json.dumps() with indent=2 for human-readable output
  • Always specify encoding='utf-8' when opening JSON files
  • Always wrap parsing in try/except json.JSONDecodeError for untrusted input
  • Use a custom JSONEncoder to handle datetime, Decimal, and custom objects
  • Use orjson when performance matters for large datasets

Want these tools available offline? The DevToolkit Bundle ($9 on Gumroad) packages 40+ developer tools into a single downloadable kit — no internet required.

Free Developer Tools

If you found this article helpful, check out DevToolkit — 40+ free browser-based developer tools with no signup required.

Popular tools: JSON Formatter · Regex Tester · JWT Decoder · Base64 Encoder

🛒 Get the DevToolkit Starter Kit on Gumroad — source code, deployment guide, and customization templates.

Top comments (0)