Python treats JSON as a first-class citizen through its standard-library json module. Because JSON objects map almost perfectly onto Python dictionaries, moving between an API payload and native Python data takes one function call. In this lesson of our JSON tutorial series, we cover the four core functions, file handling, real API responses, and the pretty-printing options that make debugging pleasant.
The json module gives you two pairs of functions, one pair for strings and one for files:
| Function | Direction | Works with |
|----------|-----------|------------|
| json.loads | JSON string -> Python | strings |
| json.dumps | Python -> JSON string | strings |
| json.load | JSON file -> Python | file objects |
| json.dump | Python -> JSON file | file objects |
The trailing s means string. Mixing them up is the most common beginner error.
import json
text = '{"name": "Ada", "age": 36, "skills": ["math", "logic"]}'
user = json.loads(text)
print(user["name"]) # Ada
print(user["skills"][0]) # math
print(type(user)) # <class 'dict'>Type mapping is predictable: objects become dicts, arrays become lists, strings stay strings, numbers become int or float, true/false become True/False, and null becomes None.
data = {"product": "Keyboard", "price": 89.99, "inStock": True}
print(json.dumps(data))
# {"product": "Keyboard", "price": 89.99, "inStock": true}Useful keyword arguments:
indent=2 pretty-prints with indentation.sort_keys=True orders keys alphabetically, which produces stable diffs.ensure_ascii=False keeps non-ASCII characters readable instead of escaping them.with open("config.json", "r", encoding="utf-8") as f:
config = json.load(f)
config["debug"] = False
with open("config.json", "w", encoding="utf-8") as f:
json.dump(config, f, indent=2)Always open JSON files with UTF-8 encoding; the JSON specification requires it.
Invalid input raises json.JSONDecodeError, which carries the line and column of the failure:
try:
json.loads("{bad json}")
except json.JSONDecodeError as e:
print(f"Parse failed at line {e.lineno}, column {e.colno}: {e.msg}")The popular requests library decodes responses directly with .json():
import requests
resp = requests.get("https://api.github.com/repos/python/cpython")
repo = resp.json()
print(repo["stargazers_count"])json.dumps raises TypeError on objects it does not understand, such as datetime or your own classes. Fix it with the default hook: json.dumps(data, default=str) converts unknown objects with str(), or supply a function that returns a serializable representation.
loads/dumps handle strings; load/dump handle files.null mapping to None.indent, sort_keys, and ensure_ascii=False for human-friendly output.json.JSONDecodeError and use the default hook for custom types.Next up: JSON and REST APIs, where JSON becomes the request and response language of web services.