JSON persistence
JSON (JavaScript Object Notation) is the standard text format for structured data — it's what APIs speak, and it's a clean way to save a dict or list to disk. The json module converts between Python objects and JSON text.
There are two pairs, and mixing them up is the #1 trap. The ones with s work on strings; the ones without work on files:
json.dumps(obj)→ returns a JSON string (s= string).json.loads(text)→ parses a JSON string back to Python.json.dump(obj, f)→ writes JSON to an open filef.json.load(f)→ reads JSON from an open file.
The type mapping is mostly what you'd expect, with a few renames: Python dict→object, list/tuple→array, str→string, True/False→true/false, and importantly None→null. Pass indent=2 to dumps/dump for pretty, human-readable output.
Syntax
import json
json.dumps(obj) # → JSON string
json.loads('{"a": 1}') # → Python dict
with open(path, 'w') as f:
json.dump(obj, f) # write to file
with open(path) as f:
data = json.load(f) # read from file
json.dumps(obj, indent=2) # pretty-printedWorked examples
Save a dict to disk and load it back
import json
data = {'name': 'Riley', 'score': 99, 'tags': ['a', 'b']}
with open('/tmp/save.json', 'w') as f:
json.dump(data, f)
with open('/tmp/save.json') as f:
loaded = json.load(f)
print(loaded == data) # True (roundtrip preserved it)String roundtrip with dumps / loads (no file)
import json
data = {'tasks': ['a', 'b'], 'done': False}
text = json.dumps(data)
print(text)
# Output:
# {"tasks": ["a", "b"], "done": false}
print(json.loads(text) == data) # TrueType mapping + pretty-printing
import json
print(json.dumps({'on': True, 'off': False, 'missing': None}))
# Output:
# {"on": true, "off": false, "missing": null}
print(json.dumps({'a': 1, 'b': [2, 3]}, indent=2))
# Output:
# {
# "a": 1,
# "b": [
# 2,
# 3
# ]
# }Common mistakes & gotchas
dump/dumps — the s is everything
json.dump(data, f) writes to a file; json.dumps(data) returns a string. Swap them and you'll either pass a file where a string is expected, or try to .write() nothing. Memory hook: s = string.
None becomes null, and dict keys become strings
JSON has no None — it becomes null, and loads back as None. Also, all object keys are strings in JSON, so json.dumps({1: "a"}) gives {"1": "a"} and you get the *string* "1" back, not the int.
Not everything is JSON-serialisable
json.dumps handles dicts, lists, strings, numbers, bools and None. Hand it a set, a datetime, or a custom object and it raises TypeError: ... is not JSON serializable. Convert to a supported type first (e.g. a date to its .isoformat() string).
Why it matters
JSON is the lingua franca of the modern backend — every web API returns it, config files use it, and it's the simplest reliable way to persist structured data between runs. The `json` module is a tool you'll touch in almost every real project that talks to the outside world.