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))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"))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"))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.
Walk nested JSON
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))
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.
A settings file
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"))
Press Run to try your code, then Check answer to grade it.Check yourself
json.loads('{"a": null, "b": true}') returns…
Tip: use the ← and → keys to move between lessons.