Lesson 19 of 34 · 0 of 2 exercises solved

Working with JSON

is the common format of APIs, config files and data exports. Python's json turns it into dicts and and back again in one call each.

json.loads parses a ; json.dumps produces one. Objects become dicts, arrays become , strings stay strings, numbers become int or float, true/false/null become True/False/.

import json

text = '{"name": "Maya", "age": 28, "hobbies": ["climbing", "chess"], "member": true, "manager": null}'
record = json.loads(text)
print(type(record), record["hobbies"][0], record["member"], record["manager"])

print(json.dumps(record))
print(json.dumps(record, indent=2, sort_keys=True))
Python (loads on first run)Ctrl+Enter runs

For files use json.load and json.dump (no s). Nested data is just nested dicts and lists, so walk it with the usual indexing and . dict.get with a default protects you from missing keys.

import json
from pathlib import Path

library = {
    "branch": "Riverside",
    "shelves": [
        {"topic": "fiction", "books": [{"title": "The Hobbit", "pages": 400}]},
        {"topic": "science", "books": [{"title": "Cosmos", "pages": 120}, {"title": "The Selfish Gene", "pages": 60}]},
    ],
}
Path("library.json").write_text(json.dumps(library, indent=2))

loaded = json.load(open("library.json"))
for shelf in loaded["shelves"]:
    total = sum(b["pages"] for b in shelf["books"])
    print(f"{shelf['topic']:<8} {len(shelf['books'])} books, {total} pages")

print(loaded.get("address", "no address key"))
Python (loads on first run)Ctrl+Enter runs

Not everything serialises. Dates, , Decimal and your own classes raise TypeError. The default= lets you tell dumps how to convert them; for the reverse direction, post- the loaded dict.

import json
from datetime import date
from dataclasses import dataclass, asdict

@dataclass
class Event:
    name: str
    day: date

def to_json(obj):
    if isinstance(obj, date):
        return obj.isoformat()
    raise TypeError(f"cannot serialise {type(obj).__name__}")

events = [Event("Team lunch", date(2026, 7, 11)), Event("Product launch", date(2026, 11, 1))]
text = json.dumps([asdict(e) for e in events], default=to_json)
print(text)

back = [Event(d["name"], date.fromisoformat(d["day"])) for d in json.loads(text)]
print(back[0].day.strftime("%d %B"))
Python (loads on first run)Ctrl+Enter runs

Common question

Is JSON the same as a Python dictionary?

JSON is a text format for structured data (objects, arrays, strings, numbers, and null) that almost every language can read and write. Python maps it onto dicts and lists, so once loaded you handle it with ordinary indexing and loops. Because it is everywhere in APIs, config files and data exchange, it is the format a Python programmer meets most often.

Load with json.load or loads, save with json.dump or dumps, and pretty-print with when people will read it. Convert non-JSON types explicitly on the way out and restore them on the way in. Validate what you load before trusting it, because it came from outside your program.

Source: RFC 8259 defines JSON as "a lightweight, text-based, language-independent data interchange format." It is a text format, not a data structure.

Common mix-ups

Each of these sounds reasonable. Think about why it is wrong, then open the explanation.

  • JSON text looks exactly like a dict literal, so they're the same thing.

  • Any Python object can be dumped to JSON.

  • JSON files can have comments and trailing commas, like Python code.

Practice

Write total_pages(text) that parses the JSON above (a dict with a shelves list, each with books that have pages) and returns the total page count across every shelf.

Exercise

Walk nested JSON

3 checks
import json

TEXT = '{"shelves": [{"topic": "fiction", "books": [{"title": "A", "pages": 400}]}, {"topic": "science", "books": [{"title": "B", "pages": 120}, {"title": "C", "pages": 60}]}]}'


def total_pages(text):
    ...


print(total_pages(TEXT))
 
Python (loads on first run)Ctrl+Enter runs
Output
Press Run to try your code, then Check answer to grade it.

Write save_settings(path, settings) and load_settings(path). Saving must write pretty-printed JSON with sorted keys; loading must return the dict, or an empty dict if the file does not exist.

Exercise

A settings file

3 checks
import json
from pathlib import Path


def save_settings(path, settings):
    ...


def load_settings(path):
    ...


save_settings("settings.json", {"theme": "dark", "sounds": True})
print(load_settings("settings.json"))
print(load_settings("missing.json"))
 
Python (loads on first run)Ctrl+Enter runs
Output
Press Run to try your code, then Check answer to grade it.

Check yourself

Quick check

json.loads('{"a": null, "b": true}') returns…

Finished reading?2 exercises still open. You can come back to them later.

Tip: use the ← and → keys to move between lessons.