Read & Write JSON with json Module
Learn to read and write JSON data using Python's json module with a practical, step-by-step lesson. Covers core concepts, hands-on walkthrough, troubleshooting, and next steps.
Focus: read and write json data with json module
Every real-world Python application eventually needs to talk to another service, save configuration, or store structured data. That's where JSON comes in — and Python's built-in json module makes reading and writing JSON data as easy as opening a file. Without it, you'd be stuck manually parsing strings, handling nested structures, and fighting with data types. This lesson will turn you from a JSON novice into someone who can confidently serialize and deserialize Python objects in seconds.
The problem this lesson solves
Imagine you've built a weather script that collects data from an API. The API returns a string like '{"temp": 72, "city": "Berlin"}'. How do you turn that string into a Python dictionary you can use? Or suppose you need to save your app's state overnight — you want to write {'user': 'alice', 'score': 4500} to a file and load it back tomorrow. Writing your own parser is error-prone, slow, and fragile. The json module handles all of that: converting Python objects to JSON strings (serialization) and JSON strings back to Python objects (deserialization). It's built-in, battle-tested, and works with files, strings, and network streams.
Core concept / mental model
Think of the json module as a translator between Python land and JSON land.
- Serialization (Python → JSON): You have a Python dict, list, string, number, boolean, or
None. Thejsonmodule turns it into a JSON-formatted string or writes it directly to a file. - Deserialization (JSON → Python): You have a JSON string or a file containing JSON. The
jsonmodule parses it and returns the corresponding Python object.
The mapping is almost one-to-one:
| Python | JSON | Example |
|---|---|---|
dict |
object | {'name': 'Bob'} → {"name": "Bob"} |
list / tuple |
array | [1, 2, 3] → [1, 2, 3] |
str |
string | 'hello' → "hello" |
int / float |
number | 42 → 42 |
True / False |
boolean | True → true |
None |
null | None → null |
Pro tip: JSON object keys must be strings. Python dicts can have non-string keys, but
json.dumps()will raise aTypeErrorunless you pass a custom encoder. Stick to string keys for smooth serialization.
The core functions you'll use every day are:
- json.dumps() — serialize to a string
- json.loads() — deserialize from a string
- json.dump() — serialize and write to a file
- json.load() — read from a file and deserialize
How it works step by step
Step 1: Import the module
import json — it's part of the standard library, no pip install needed.
Step 2: Serialize a Python object to a JSON string
import json
data = {
"name": "Alice",
"age": 30,
"hobbies": ["reading", "hiking"],
"is_active": True,
"address": None
}
json_string = json.dumps(data, indent=2)
print(json_string)
Expected output:
{
"name": "Alice",
"age": 30,
"hobbies": ["reading", "hiking"],
"is_active": true,
"address": null
}
Notice Python's True becomes JSON true, None becomes null. The indent=2 makes the output human-readable — omit it for minified output.
Step 3: Deserialize a JSON string back to Python
import json
json_string = '{"name": "Bob", "age": 25, "active": false}'
parsed = json.loads(json_string)
print(parsed)
print(type(parsed))
print(parsed["name"])
Expected output:
{'name': 'Bob', 'age': 25, 'active': False}
<class 'dict'>
Bob
Step 4: Write Python objects to a file
import json
config = {
"host": "localhost",
"port": 8080,
"debug": True
}
with open("config.json", "w") as f:
json.dump(config, f, indent=4)
Now check config.json — it contains:
{
"host": "localhost",
"port": 8080,
"debug": true
}
Step 5: Read JSON from a file
import json
with open("config.json", "r") as f:
loaded_config = json.load(f)
print(loaded_config["host"]) # localhost
Pro tip: Always use
with open(...)to ensure the file is properly closed, even if an exception occurs.
Hands-on walkthrough
Let's build a mini contact book that saves and loads contacts from a JSON file.
import json
# Sample contacts data
contacts = [
{"name": "Ana", "phone": "555-0100", "email": "ana@example.com"},
{"name": "Ben", "phone": "555-0200", "email": "ben@example.com"}
]
# Save to file
with open("contacts.json", "w") as f:
json.dump(contacts, f, indent=2)
print("Contacts saved to contacts.json")
# Load back
with open("contacts.json", "r") as f:
loaded_contacts = json.load(f)
# Add a third contact
loaded_contacts.append({
"name": "Carmen",
"phone": "555-0300",
"email": "carmen@example.com"
})
# Save updated list
with open("contacts.json", "w") as f:
json.dump(loaded_contacts, f, indent=2)
print("Final contacts:")
for c in loaded_contacts:
print(f" {c['name']} — {c['email']}")
Expected output:
Contacts saved to contacts.json
Final contacts:
Ana — ana@example.com
Ben — ben@example.com
Carmen — carmen@example.com
Now inspect contacts.json — it's a valid JSON array with three objects.
Compare options / when to choose what
| Function | Use Case | Returns/Writes To | Example |
|---|---|---|---|
json.dumps() |
Convert Python object to JSON string (e.g., send via HTTP) | String | json.dumps({'a': 1}) |
json.loads() |
Parse JSON string from API or user input | Python object | json.loads('{"a": 1}') |
json.dump() |
Write Python object directly to a file | File object | json.dump(data, f) |
json.load() |
Read JSON from a file | Python object | json.load(f) |
When should you use dumps+loads vs dump+load?
- Use
dumps/loadswhen you're working with strings: API responses, environment variables, or in-memory operations. - Use
dump/loadwhen you have a file path or file-like object: configuration files, data persistence, output logs.
Other serialization libraries:
- pickle (Python-specific, can serialize custom objects but unsafe)
- yaml (more human-readable config, needs pyyaml)
- orjson (faster, but third-party)
Stick with json for interoperability and safety in most cases.
Troubleshooting & edge cases
1. TypeError: Object of type datetime is not JSON serializable
Problem: You're trying to serialize a datetime object, which Python doesn't know how to convert to JSON.
Solution: Convert to a string first, or pass a custom encoder.
import json
from datetime import datetime
now = datetime.now()
# This will fail:
# json.dumps(now)
# Solution: convert to string
json.dumps(str(now)) # '"2025-03-15 14:30:00.123456"'
2. json.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Problem: You're trying to parse an empty string, a file with no content, or malformed JSON.
Solution: Check the file contents first, validate with a try-except.
import json
data_string = "" # empty
try:
result = json.loads(data_string)
except json.JSONDecodeError as e:
print(f"Invalid JSON: {e}")
3. Unicode characters turn into \uXXXX sequences
Problem: Japanese, emoji, or other Unicode characters are escaped.
Solution: Use ensure_ascii=False.
json.dumps({'emoji': '😊'}, ensure_ascii=False)
# '{"emoji": "😊"}'
4. Non-string dictionary keys
Problem: json.dumps({1: 'one'}) raises TypeError: keys must be str, int, float, bool or None.
Solution: Convert keys to strings explicitly.
import json
data = {1: 'one', 2: 'two'}
json.dumps({str(k): v for k, v in data.items()})
# '{"1": "one", "2": "two"}'
What you learned & what's next
You now know how to:
- Explain what the json module does and why it's essential
- Serialize Python objects to JSON strings and files using json.dumps() and json.dump()
- Deserialize JSON strings and files back to Python objects using json.loads() and json.load()
- Handle common edge cases like non-serializable types, empty data, and Unicode characters
- Choose between dumps/dump and loads/load based on your use case
Next step: In the next lesson, you'll learn how to work with CSV files using Python's csv module — another ubiquitous data format for spreadsheets and data exports.
Practice recap
Open a Python REPL or create a script. Write a simple dictionary with your name, age, and a list of your favorite books. Use json.dumps() to serialize it, then json.loads() to deserialize it back. Save the dictionary to a file named favorites.json and read it back with json.load(). Now try adding a datetime object — see the error, then fix it by converting to a string.
Common mistakes
- Forgetting to open the file in write (
'w') or read ('r') mode — using'w+'for reading will overwrite the file before you can load it. - Assuming
json.load()returns a string — it returns a Python dict/list/etc., already parsed. - Trying to serialize custom objects (like
datetimeorclassinstances) without a default serializer — always convert to a primitive type first. - Ignoring
json.JSONDecodeError— wrapjson.loads()in a try-except when handling untrusted data.
Variations
- Use
json.dumps(data, indent=2, sort_keys=True)to produce sorted, pretty-printed output for configuration files. - For high-performance JSON processing, consider
orjsonorujson— drop-in replacements that are faster, but the standardjsonmodule is fine for most apps. - If you need to serialize complex Python objects (like custom classes), write a custom
JSONEncodersubclass or usedefault=strinjson.dumps().
Real-world use cases
- Saving user preferences or game state to a local JSON file so data persists between app launches.
- Parsing API responses from web services (most REST APIs return JSON) using
json.loads(response.text). - Reading configuration files (e.g.,
config.json) for Python applications —json.load(open('config.json')).
Key takeaways
- Python's
jsonmodule has four main functions:dumps,loads,dump,loadfor serialization and deserialization. - JSON can only store dicts, lists, strings, numbers, booleans, and
null— convert other types to these before serializing. - Use
json.dump(obj, file)andjson.load(file)when working with files,dumps/loadsfor in-memory strings. - Always handle
json.JSONDecodeErrorwhen parsing untrusted JSON to avoid crashes. - Add
indent=2for human-readable output andensure_ascii=Falseto preserve Unicode characters. - The
jsonmodule is part of Python's standard library — no external dependencies required.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.