February 1, 2025 - 10 min read

How to Parse JSON in Python

A complete guide to reading, writing, and handling JSON data in Python using the built-in json module and popular libraries.

pythonparsing

Python's built-in json module makes working with JSON data straightforward. Whether you're consuming a REST API, reading config files, or processing data pipelines, understanding how to correctly parse, serialize, and handle JSON in Python is an essential skill for every developer.

This guide covers everything from simple parsing with json.loads() to handling files, nested structures, custom encoders, and the edge cases that trip up even experienced developers.

Python JSON tutorial placement

Advertisement placeholder -- this space is reserved for contextual ads once the site is approved.

The json Module Basics

Python ships with the json module in its standard library — no installation required. It provides four core functions:

  • json.loads(string) — parse a JSON string into a Python object
  • json.dumps(obj) — serialize a Python object to a JSON string
  • json.load(file) — parse JSON from a file object
  • json.dump(obj, file) — write a Python object as JSON to a file
import json

# Parse a JSON string
json_string = '{"name": "Alice", "age": 30, "active": true}'
data = json.loads(json_string)

print(data["name"])    # Alice
print(data["age"])     # 30
print(type(data))      # <class 'dict'>

Type Mapping

Python maps JSON types to their closest native equivalents: JSON objects become dict, arrays become list, strings becomestr, numbers become int or float, booleans become bool, and null becomes None.

Reading and Writing JSON Files

Working with JSON files is one of the most common tasks. Always open files with encoding="utf-8" to avoid decoding errors on Windows systems.

import json

# Reading JSON from a file
with open("data.json", "r", encoding="utf-8") as f:
    data = json.load(f)

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

The indent parameter controls pretty-printing, and ensure_ascii=False preserves Unicode characters like accents and emoji — essential for international applications.

Mid-article Python JSON placement

Advertisement placeholder -- this space is reserved for contextual ads once the site is approved.

Parsing JSON from API Responses

The requests library provides a convenient .json() method that automatically parses the response body:

import requests

response = requests.get("https://api.example.com/users/1")

if response.status_code == 200:
    user = response.json()  # Automatically parsed
    print(user["name"])
else:
    print(f"Error: {response.status_code}")

Handling Nested JSON

Nested JSON objects are simply nested Python dicts. Access them with chained bracket notation or use .get() to avoid KeyError on missing keys:

data = {
    "user": {
        "profile": {
            "address": {"city": "London"}
        }
    }
}

# Safe access with .get() — returns None instead of raising KeyError
city = data.get("user", {}).get("profile", {}).get("address", {}).get("city")
print(city)  # London

Custom Serialization

Python's json module can't serialize objects like datetime, Decimal, or custom classes by default. Solve this with 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 float(obj)
        return super().default(obj)

data = {"created_at": datetime.now(), "price": Decimal("9.99")}
print(json.dumps(data, cls=CustomEncoder))

Error Handling

Always wrap JSON parsing in try/except to handle malformed input gracefully. The specific exception to catch is json.JSONDecodeError (a subclass of ValueError):

import json

def safe_parse(text: str):
    try:
        return json.loads(text)
    except json.JSONDecodeError as e:
        print(f"JSON parse error: {e.msg} at line {e.lineno}, col {e.colno}")
        return None

result = safe_parse('{"broken": }')  # Invalid JSON
# JSON parse error: Expecting value at line 1, col 12

Key Takeaways

  • Use json.loads() for strings and json.load() for files
  • Always specify encoding="utf-8" when opening JSON files
  • Use .get() for safe access to nested keys
  • Write a custom JSONEncoder for datetime and Decimal types
  • Catch json.JSONDecodeError to handle malformed input gracefully
  • Use JSONStudio to validate and format JSON before processing it in Python

Continue learning

How JSON Works

Learn how parsers tokenize documents, how serialization travels across the network, and ways to debug encoding bugs.

Jan 6, 2025 · 10 min read

What is JSON?

A foundational tour of JSON covering syntax, design goals, and why it became the lingua franca for data on the web.

Jan 5, 2025 · 9 min read

JSON vs XML

An objective look at how both formats handle validation, streaming, and readability so you can choose for each project.

Jan 7, 2025 · 11 min read