Skip to content
Back to Learn
·10 min read

How to Read and Write JSON in Python

Python is one of the most popular languages for working with JSON, thanks to its built-in json module, its rich ecosystem of data validation libraries (Pydantic, attrs, dataclasses), and its dominance in data science and backend development. This comprehensive guide covers everything from basic parsing to advanced patterns like custom encoders, streaming, and dataclass generation. Use our JSON to Python tool to generate code from your JSON samples instantly.

Complete JSON Parsing in Python

The json module provides four core functions:

FunctionInputOutputUse Case
json.loads()StringPython objectParse JSON from memory (API response, string variable)
json.load()File objectPython objectParse JSON from a file on disk
json.dumps()Python objectStringSerialize to string (API request, storage)
json.dump()Python objectFile objectWrite JSON to a file

Basic Parsing with Error Handling

import json
from json import JSONDecodeError

# Parse from string with comprehensive error handling
json_string = '{"name": "Alice", "age": 30, "skills": ["Python", "JSON"]}'
try:
    data = json.loads(json_string)
    print(data["name"])       # Alice
    print(data.get("nickname", None))  # Safe access with default
except JSONDecodeError as e:
    print(f"Parse error at line {e.lineno}, col {e.colno}: {e.msg}")
    print(f"Character position: {e.pos}")
    print(f"Context: ...{e.doc[max(0,e.pos-20):e.pos+20]}...")

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

Serialization: Python to JSON

Control every aspect of JSON output with json.dumps() parameters:

data = {
    "name": "Alice",
    "age": 30,
    "active": True,
    "score": None,
    "tags": ["python", "json"],
    "metadata": {"version": 2}
}

# Pretty-printed (development)
print(json.dumps(data, indent=2, ensure_ascii=False))

# Compact for production (40% smaller)
print(json.dumps(data, separators=(",", ":")))

# Sorted keys (deterministic, diff-friendly)
print(json.dumps(data, sort_keys=True, indent=2))

# Custom fallback for non-serializable types
print(json.dumps(data, default=str))

Python-to-JSON Type Mapping Reference

Python TypeJSON TypeExampleNotes
dictObject{"key": "value"}Keys must be strings
list, tupleArray[1, 2, 3]Tuples become lists (type information lost)
strString"hello"Unicode fully supported
intNumber42JSON has no integer/float distinction
floatNumber3.14NaN and Infinity become null
boolBooleantrue, falseTrue/False map to lowercase
NoneNullnullCorrect representation of absence
datetimeString (ISO 8601)"2026-07-06T12:00:00"Not serializable by default; use default=str or custom encoder
DecimalNumber10.50Converts to float with potential precision loss
setNot supportedRaises TypeErrorConvert to list first: list(my_set)

Custom JSONEncoder for Complex Types

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

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

# Usage
data = {
    "name": "Alice",
    "created": datetime.now(),
    "price": Decimal("19.99"),
    "unique_ids": {1, 2, 3}
}
json_str = json.dumps(data, cls=CustomEncoder, indent=2)

Generating Python Dataclasses from JSON

For type safety and IDE autocompletion, generate Python dataclasses from your JSON data. Our JSON to Python tool produces fully-typed dataclass definitions with proper type annotations, nested class support, and Optional fields for nullable values:

# Generated by JSON to Python converter
from dataclasses import dataclass
from typing import List, Optional

@dataclass
class Address:
    street: str
    city: str
    zip_code: Optional[str] = None

@dataclass
class User:
    name: str
    age: int
    email: str
    address: Address
    tags: List[str]

Pydantic v2 Models for Runtime Validation

For production applications, Pydantic v2 provides runtime validation with detailed error messages. Our JSON to Pydantic v2 tool creates models with field validation, default values, and JSON schema export:

from pydantic import BaseModel, EmailStr, Field
from typing import List, Optional

class UserModel(BaseModel):
    name: str = Field(..., min_length=1, max_length=100)
    age: int = Field(..., ge=0, le=150)
    email: EmailStr
    tags: List[str] = []

# Auto-validation on construction
user = UserModel(name="Alice", age=30, email="alice@example.com")
print(user.model_dump_json(indent=2))

Streaming Large JSON Files

For JSON files too large to fit in memory, use ijson for streaming parsing, or convert to NDJSON (newline-delimited JSON) for line-by-line processing. Use our JSON to NDJSON converter to prepare data for streaming:

import json

# Process a large NDJSON file line by line
with open("large_data.ndjson", "r") as f:
    for line in f:
        if line.strip():
            record = json.loads(line)
            process_record(record)

Common Pitfalls and Edge Cases

  • Tuple loss — Tuples serialize as JSON arrays; when parsed back, they become lists. Use object_hook parameter to restore types
  • Precision loss — Large integers (> 2^53) lose precision in JavaScript. Use strings for 64-bit integer IDs
  • NaN handlingfloat('nan') becomes null in JSON with no way to distinguish from actual null
  • Circular references — Objects referencing themselves raise ValueError. Use a custom default handler or refactor data
  • Encoding issues — Always specify encoding="utf-8" when reading/writing JSON files for cross-platform compatibility
  • Duplicate keys — Python's json.loads() silently keeps the last value for duplicate keys. Use our Duplicate Key Detector to catch these

Next Steps

Generate Python code from your JSON with our JSON to Python. For Pydantic models with runtime validation, use JSON to Pydantic v2. Validate your JSON first with JSON Validator to avoid errors.