Working with JSON
JSON is just text — and it maps directly onto dicts and lists
JSON (JavaScript Object Notation) is a plain-text format for structured data — and not coincidentally, it’s shaped almost exactly like Python’s own dicts and lists, which is a large part of why it’s the default format for API requests/responses, config files, and tool-call arguments alike:
{
"name": "research_agent",
"model": "claude-sonnet",
"temperature": 0.7,
"tags": ["search", "reasoning"]
}(a plain JSON file, shown for reference — not Python code, not run live)
Read that side by side with a Python dict literal and the resemblance is immediate:
- JSON objects become dicts
- JSON arrays become lists
- JSON strings/numbers/booleans/
nullbecomestr/intorfloat/bool/None
The json module (part of the standard library — no install needed)
converts between the two directly.
Reading JSON from a file: json.load
json.load(f) takes an already-open file object (note: not a filename —
you still need
with open(...) from the previous section
to get one) and parses its entire contents into ordinary Python data —
here, a dict, since the file’s top level is a JSON object. Once parsed,
it’s just a regular dict — every
dict operation from the data structures lesson
applies normally.
Writing JSON to a file: json.dump
The reverse direction — converting Python data into JSON text and writing
it to a file — uses json.dump:
import json
config = {
"name": "research_agent",
"model": "claude-sonnet",
"temperature": 0.7,
"tags": ["search", "reasoning"],
}
with open("config.json", "w") as f:
json.dump(config, f, indent=2)(writes a file — not run live in this format, but produces the exact file shown at the top of this section, reformatted with indent=2)
indent=2 is optional but worth using by default for anything a human
might read later — without it, json.dump writes the most compact form
possible, all on one line, which is valid JSON but painful to read.
json.loads / json.dumps — the string versions
Sometimes JSON arrives as a string you already have in memory — an API
response body, for instance — rather than something sitting in a file.
json.loads (load string) and json.dumps (dump to a string) do
the same conversions, without any file involved:
The naming is consistent across all four: load/dump work with an
already-open file object; loads/dumps work with a plain string — the
s suffix specifically flags “string,” not “load safely” or anything
else. It’s easy to reach for the wrong one out of habit, so it’s worth
checking which you actually have (a file object, or a string) before
picking which function to call.
When the JSON itself is malformed: JSONDecodeError
Parsing can fail — the text might not actually be valid JSON at all (a trailing comma, a missing quote, truncated data from a network error):
JSONDecodeError is a normal exception, catchable exactly like any other
from the Python setup lesson’s error handling concept:
This matters specifically because JSON so often arrives from somewhere you don’t control — a file someone else edited by hand, a flaky network response — so treating parsing as something that can fail, rather than assuming it always succeeds, is the realistic default here.
What Python type does a top-level JSON object ({...}) become once parsed?