JSON is the most common format for configuration files and web APIs. In Python, JSON data maps naturally to dictionaries and lists, so once you understand the basics of data types, working with JSON becomes straightforward. This guide shows how to read JSON from a file, write it back, and avoid a few common mistakes beginners make.

1. When to use JSON in Python

You will see JSON when:

  • Reading configuration from a file like config.json.
  • Calling a web API with requests (see HTTP GET requests).
  • Saving data from your program in a simple, language‑neutral format.

JSON objects become Python dict, JSON arrays become Python list, and other basic types map to str, int, float, bool, or None.

2. Basic reading: json.load()

To read JSON from a file, use json.load() with a file object opened in text mode:

import json

with open("data.json", "r", encoding="utf-8") as f:
    data = json.load(f)

print(type(data))  # usually dict or list
print(data)

Typical data.json content might look like:

{
  "name": "Alice",
  "age": 30,
  "languages": ["Python", "JavaScript"],
  "active": true
}

After loading, you access fields just like any other dictionary, as described in Dictionaries:

print(data["name"])          # Alice
print(data["languages"][0]) # Python

2.1 Handling missing keys safely

If a key may not be present, use dict.get() to avoid KeyError:

country = data.get("country", "Unknown")
print(country)

3. Basic writing: json.dump()

To write JSON to a file, build a dictionary or list and pass it to json.dump(). Use indent=2 to make the file readable for humans.

import json

data = {
    "name": "Alice",
    "age": 30,
    "languages": ["Python", "JavaScript"],
    "active": True,
}

with open("out.json", "w", encoding="utf-8") as f:
    json.dump(data, f, indent=2)

If you only need a JSON string in memory (for logging or sending over the network), use json.dumps() instead:

json_str = json.dumps(data, indent=2)
print(json_str)

4. Reading and writing lists of objects

JSON files often contain a list of similar objects, such as users or products. You can treat this as a list of dictionaries:

import json

payload = [
    {"id": 1, "title": "Learn Python", "done": False},
    {"id": 2, "title": "Build a small app", "done": True},
]

with open("todos.json", "w", encoding="utf-8") as f:
    json.dump(payload, f, indent=2)

with open("todos.json", "r", encoding="utf-8") as f:
    todos = json.load(f)

for todo in todos:
    status = "✓" if todo["done"] else "·"
    print(status, todo["title"])

5. Working with JSON from HTTP APIs

When using requests, you often get JSON directly from response.json():

import requests

resp = requests.get("https://api.example.com/users/1", timeout=5)
resp.raise_for_status()

data = resp.json()   # already a dict / list
print(data["name"])

This is the same structure you get from json.load(), so all techniques in this guide still apply. For more about HTTP, see How to send HTTP GET requests.

6. Common JSON pitfalls

Here are some issues new Python developers often run into when working with JSON:

  • Using single quotes in JSON files: Valid JSON must use double quotes around keys and string values. Python accepts single quotes in code, but the JSON file must follow JSON rules.
  • Trying to dump non‑serializable objects: You cannot directly dump datetime objects, custom classes, or open file handles. Convert them to strings or dicts first.
  • Forgetting encoding="utf-8" on Windows: Without an explicit encoding you may see strange characters for non‑ASCII text.
  • Confusing JSON strings and Python dictionaries: A JSON string is text; you must call json.loads() to turn it into a dict.

6.1 Example: handling non‑serializable fields

import json
from datetime import datetime

raw = {
    "name": "Report",
    "created_at": datetime.utcnow(),  # not directly JSON-serializable
}

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

json_str = json.dumps(raw, default=default, indent=2)
print(json_str)

7. Validating and pretty‑printing JSON

Sometimes you receive a JSON string and want to check if it is valid and view it in a readable format. You can round‑trip it through json.loads() and json.dumps():

import json

raw = '{"name": "Alice", "age": 30}'

try:
    parsed = json.loads(raw)
except json.JSONDecodeError as e:
    print("Invalid JSON:", e)
else:
    print(json.dumps(parsed, indent=2))

8. Summary and next steps

You have seen how JSON maps cleanly onto Python dict and list, how to read and write it with json.load() and json.dump(), and how to avoid common pitfalls when dealing with real‑world data. These skills are essential when you move on to web APIs, configuration files, and small automation tools.

From here you can:

  • Review Data types to strengthen your understanding of how JSON values behave in Python.
  • Learn to persist more complex data structures with CSV files and databases such as SQLite.
  • Combine JSON with frameworks like FastAPI to build your own APIs.