Python JSON Serialization Guide
JSON (JavaScript Object Notation) is the universal standard format for transmitting structured data across the web, REST APIs, and microservices.
Python's built-in json module handles bidirectional translation between Python data structures and JSON text according to a strict type translation specification:
| Python Object | JSON Equivalent | Notes |
|---|---|---|
dict | object ({...}) | Keys are automatically converted to strings |
list, tuple | array ([...]) | Tuples are serialized to JSON arrays |
str | string | UTF-8 encoded string |
int, float | number | Arbitrary precision preserved |
True / False | true / false | Lowercase boolean literals |
None | null | Null reference literal |
# Inspecting Python to JSON Type Conversion
import json
python_payload = {
"user_id": 101,
"username": "balaji_dev",
"is_admin": True,
"roles": ("Backend", "DevOps"), # Tuple becomes Array
"profile": None, # None becomes null
"rating": 4.95
}
# Serialize Python dictionary to JSON string:
json_string = json.dumps(python_payload)
print("JSON Output String:")
print(json_string)
Truebecomes lowercasetrue.Nonebecomesnull.- Tuple
("Backend", "DevOps")becomes JSON square bracket array["Backend", "DevOps"].
The two primary in-memory functions have an "s" (string) suffix:
json.dumps(obj, indent=4, sort_keys=True): Serializes a Python object into a formatted JSON string (Dump String).json.loads(json_str): Parses a JSON string into Python native dictionaries/lists (Load String).
import json
# 1. Pretty printing JSON with indent=4 and sorted keys:
server_config = {
"host": "127.0.0.1",
"port": 8000,
"debug": False,
"allowed_hosts": ["localhost", "ourcompiler.com"]
}
pretty_json = json.dumps(server_config, indent=4, sort_keys=True)
print("--- ๐
Pretty Formatted JSON ---")
print(pretty_json)
# 2. Deserializing raw JSON string back to Python Dictionary:
raw_api_response = '{"status": 200, "message": "Success", "data": [10, 20, 30]}'
parsed_dict = json.loads(raw_api_response)
print("\n--- ๐ Parsed Python Dictionary ---")
print("Status Code:", parsed_dict["status"])
print("Data items: ", parsed_dict["data"])
print("Python Type:", type(parsed_dict).__name__)
When calling web APIs using libraries like urllib or requests, incoming JSON text streams are converted into Python native dictionaries using json.loads().
When working with physical files on disk, use the non-string functions json.dump() and json.load() which write and read directly from file streams:
json.dump(obj, file_handle): Serializes Python object directly into a writable file stream.json.load(file_handle): Reads and parses JSON directly from a readable file stream.
import json
from pathlib import Path
settings_file = Path("user_settings.json")
# Data to save to disk:
user_preferences = {
"theme": "dark",
"font_size": 14,
"auto_save": True,
"recent_files": ["main.py", "models.py", "utils.py"]
}
# 1. Write dictionary to physical JSON file on disk:
with open(settings_file, "w", encoding="utf-8") as f:
json.dump(user_preferences, f, indent=4)
print(f"โ
Saved settings to {settings_file}")
# 2. Read physical JSON file back from disk:
with open(settings_file, "r", encoding="utf-8") as f:
loaded_settings = json.load(f)
print(f"๐ Loaded Theme: {loaded_settings['theme']} | Font: {loaded_settings['font_size']}px")
# Clean up demo file:
settings_file.unlink()
Always specify encoding="utf-8" when opening JSON files to ensure emojis, symbols, and non-English text are written and read reliably across Windows and Linux.
Standard JSON does not define types for Python datetime objects or set collections. Attempting to serialize them raises a TypeError: Object of type ... is not JSON serializable.
To serialize custom types, provide a default handler function:
import json
import datetime as dt
def custom_json_serializer(obj):
"""Custom serializer handler for unsupported types."""
if isinstance(obj, (dt.datetime, dt.date)):
return obj.isoformat() # Convert to standard ISO 8601 string
if isinstance(obj, set):
return list(obj) # Convert set to JSON list
raise TypeError(f"Type {type(obj)} is not serializable!")
# Complex Python payload containing datetime and sets:
transaction = {
"invoice_id": "INV-2026-894",
"timestamp": dt.datetime.now(),
"unique_categories": {"Electronics", "Accessories"}, # Set!
"amount": 499.99
}
serialized_json = json.dumps(transaction, default=custom_json_serializer, indent=2)
print("--- ๐ก๏ธ Custom Serialized JSON ---")
print(serialized_json)
Converting datetimes to ISO 8601 strings (2026-08-14T15:30:00) ensures full compatibility across frontend JavaScript applications and databases.
Remember: json.loads(str) expects a raw JSON string argument. json.load(file) expects an open file stream object. Passing a string to json.load() raises AttributeError: 'str' object has no attribute 'read'.
Create a Python dictionary containing student details, serialize it to a pretty JSON string with 2-space indentation, and print the result.
import json
student_record = {
"name": "Alex Smith",
"grade": "12th",
"subjects": ["Math", "Physics", "Computer Science"],
"passed": True
}
json_output = json.dumps(student_record, indent=2)
print("Pretty JSON Output:")
print(json_output)
Q What is the difference between json.dumps() and json.dump()?
json.dumps() (Dump String) serializes an object into a Python string in memory. json.dump() serializes an object directly into an open file stream on disk.
Q Why does json.dumps({"a": 1}) work, but json.dumps({(1, 2): "val"}) fail?
JSON specification strictly requires object keys to be strings. Python dictionary keys that are tuples or other types cannot be converted without setting skipkeys=True.
Q How can I format JSON output to be as compact as possible for network transmission?
Use separators=(",", ":") in json.dumps(). This strips all whitespace between items and keys, minimizing packet size.