JSON
Why this matters
JSON is the format the internet uses to send structured data. It's also how you talk to LLMs in code. Every request to a model API is a JSON object, and every reply comes back as JSON. When you ask a model for structured output, such as "give me the sentiment and three keywords", you ask for JSON and then read it. Once you're fluent here, API responses stop looking like walls of brackets.
- Turn JSON text into Python data with json.loads, and back with json.dumps
- Map each JSON type to its Python equivalent
- Reach values buried in nested JSON with keys and indexes
- Format JSON readably and recognize invalid JSON
Text that looks like Python data
Think of a shipping label. It has fixed fields, such as name, street and zip code, in a layout any courier in the world can read. JSON (JavaScript Object Notation) does the same for data. It's a way of writing structured data as plain text that any program can read:
{
"campaign": "Spring Sale",
"active": true,
"budget": 5000,
"channels": ["search", "email"],
"owner": null
}
It looks almost exactly like a Python dictionary, and that's no accident. But it's text: a string of characters that any language can read and write. That's why APIs use it. The small differences from Python matter:
| JSON | Python |
|---|---|
object {"key": value} | dict |
array [1, 2, 3] | list |
string "text" (double quotes only) | str |
number 42 or 4.2 | int or float |
true / false | True / False |
null | None |
JSON also doesn't allow single quotes, comments or a trailing comma after the last item.
json.loads: from text to Python
The json module in the standard library converts between the two. json.loads ("load string") parses JSON text into Python data:
import json text = '{"campaign": "Spring Sale", "active": true, "budget": 5000, "channels": ["search", "email"], "owner": null}' data = json.loads(text) print(type(text)) print(type(data)) print(data["campaign"], data["active"], data["owner"]) print(data["channels"][1])
Before loads, you have one long string, and you can't ask it for the budget. After, you have an ordinary dictionary. true has become True, null has become None, and the array is a list you can index.
json.dumps: from Python to text
json.dumps ("dump string") goes the other way. indent adds line breaks and spacing for people. Without it, you get the compact form that programs send to each other:
import json report = {"campaign": "Spring Sale", "roas": 5.08, "flags": [], "approved": False, "notes": None} print(json.dumps(report)) print(json.dumps(report, indent=2))
Note that str(report) would not give you JSON. It uses single quotes and True/None, which other systems will reject. Always use json.dumps when something else needs to read it.
Here's the exact shape of a real request to Claude's Messages API, built as a Python dictionary and turned into JSON. The lessons on APIs show how to send it:
import json request_body = { "model": "claude-opus-5-5", "max_tokens": 300, "messages": [ {"role": "user", "content": "Write a subject line for a fall sale."} ], } print(json.dumps(request_body, indent=2))