Home› Tutorials› Standard Library
Standard LibraryJSON Handling in Python: Serialising, Deserialising, and Edge Cases
json.loads(s)parses a string;json.load(f)reads from a file object.json.dumps(obj, indent=2)produces human-readable output; omitindentfor compact wire format.jsononly handlesstr,int,float,bool,None,list,dict— pass a customdefault=function for other types.- JSON keys are always strings; Python dicts allow any hashable key, so round-trip fidelity requires care.
How do I parse a JSON string?
Use json.loads() (the s stands for string). It converts a JSON-formatted string into a Python object and raises json.JSONDecodeError — a subclass of ValueError — if the input is malformed:
import json
raw = '{"name": "Alice", "age": 30, "active": true}'
data = json.loads(raw)
print(data["name"]) # Alice
print(type(data)) # <class 'dict'>
print(data["active"]) # True (JSON true becomes Python True)
JSON's null maps to Python's None, true/false map to True/False, JSON arrays become Python lists, and JSON objects become Python dicts.
How do I read JSON from a file?
Use json.load() (no s) with a file object. Open the file in text mode with UTF-8 encoding to handle international characters correctly:
import json
with open("config.json", encoding="utf-8") as fh:
config = json.load(fh)
print(config["database"]["host"])
If you already have the file contents as a string (for example, from a network response), use json.loads() instead. The distinction is: load accepts a file-like object; loads accepts a string.
How do I serialise Python objects to JSON?
Use json.dumps() to produce a JSON string, or json.dump() to write directly to a file:
import json
data = {"name": "Bob", "scores": [95, 87, 100], "passed": True}
# To a string
s = json.dumps(data)
print(s)
# {"name": "Bob", "scores": [95, 87, 100], "passed": true}
# To a file
with open("output.json", "w", encoding="utf-8") as fh:
json.dump(data, fh)
By default, keys are sorted alphabetically only if you pass sort_keys=True. Without it they follow Python dict insertion order (Python 3.7+).
How do I pretty-print JSON?
Pass indent to either dumps or dump. An integer value sets the number of spaces per indentation level; "\t" uses a tab character:
import json
payload = {"user": {"id": 42, "roles": ["admin", "editor"]}}
print(json.dumps(payload, indent=2))
# {
# "user": {
# "id": 42,
# "roles": [
# "admin",
# "editor"
# ]
# }
# }
For wire formats and APIs, omit indent entirely and also pass separators=(",", ":") to strip the spaces after colons and commas, producing the most compact output possible.
How do I serialise types json doesn't know about?
The json module raises TypeError if it encounters a type it cannot handle, such as a datetime, a set, or a custom class instance. Supply a default function that converts unknown objects to a serialisable form:
import json
from datetime import datetime, date
def json_default(obj):
if isinstance(obj, (datetime, date)):
return obj.isoformat()
if isinstance(obj, set):
return sorted(obj) # convert to a sorted list
raise TypeError(f"Object of type {type(obj)} is not JSON serialisable")
data = {
"created": datetime(2026, 7, 1, 9, 30),
"tags": {"python", "tutorial"},
}
print(json.dumps(data, default=json_default, indent=2))
# {
# "created": "2026-07-01T09:30:00",
# "tags": ["python", "tutorial"]
# }
Alternatively, subclass json.JSONEncoder and override its default method, then pass cls=MyEncoder to dumps. The functional approach is simpler for most cases.
What are the common pitfalls?
Several mismatches between JSON and Python catch developers off-guard:
- Key type loss. JSON only has string keys. A Python dict with integer keys such as
{1: "one"}serialises to{"1": "one"}. On round-trip the key becomes the string"1", not the integer1. - Tuple becomes list. Python
(1, 2, 3)serialises to JSON[1, 2, 3]and deserialises back as a list. If tuple identity matters, do not use plain JSON. - Float precision. JSON has no decimal type. Values like
0.1 + 0.2may not round-trip exactly. UseDecimalwith a custom encoder if precision matters. - Non-ASCII characters. By default,
json.dumpsescapes non-ASCII characters to\uXXXX. Passensure_ascii=Falseto keep them as-is (and open the file withencoding="utf-8").
print(json.dumps({"city": "Munich"}, ensure_ascii=False))
# {"city": "Munich"} (not {"city": "Munich"} with escaped chars)
How do I handle large JSON files efficiently?
The standard json module loads the entire document into memory. For files that are too large to fit comfortably in RAM, consider the ijson third-party library, which provides a streaming parser:
# pip install ijson
import ijson
with open("huge.json", "rb") as fh:
for record in ijson.items(fh, "results.item"):
process(record) # handles one record at a time
For files up to a few hundred megabytes, json.load() with a buffered file object is usually fast enough. The standard library's json module is implemented in C (via _json) in CPython, so parsing speed is not often the bottleneck; memory is.
Another practical approach for moderately large files is to split them into newline-delimited JSON (NDJSON), where each line is a complete JSON object. You can then process line by line with the standard library:
with open("records.ndjson", encoding="utf-8") as fh:
for line in fh:
record = json.loads(line)
process(record)