Introduction to JSON and Python
JSON (JavaScript Object Notation) is the most common data format for APIs and configuration files. Python dictionaries map naturally to JSON objects, making conversion straightforward with the built-in json module.
Type Mapping
Python → JSON
- dict → object
- list, tuple → array
- str → string
- int, float → number
- True/False → true/false
- None → null
JSON → Python
- object → dict
- array → list
- string → str
- number → int/float
- true/false → True/False
- null → None
Converting Dictionary to JSON
import json
# Basic conversion
data = {
'name': 'Alice',
'age': 30,
'is_active': True,
'balance': None
}
# Convert to JSON string
json_string = json.dumps(data)
print(json_string)
# {"name": "Alice", "age": 30, "is_active": true, "balance": null}
# Pretty print with indentation
pretty_json = json.dumps(data, indent=2)
print(pretty_json)
# {
# "name": "Alice",
# "age": 30,
# "is_active": true,
# "balance": null
# }
# Sort keys alphabetically
sorted_json = json.dumps(data, indent=2, sort_keys=True)
# Ensure ASCII (escape non-ASCII characters)
json.dumps({'city': '東京'}, ensure_ascii=True) # {"city": "\u6771\u4eac"}
json.dumps({'city': '東京'}, ensure_ascii=False) # {"city": "東京"}Converting JSON to Dictionary
import json
# Parse JSON string to dictionary
json_string = '{"name": "Alice", "age": 30, "active": true}'
data = json.loads(json_string)
print(data) # {'name': 'Alice', 'age': 30, 'active': True}
print(type(data)) # <class 'dict'>
print(data['name']) # Alice
# Handle JSON arrays
json_array = '[{"id": 1}, {"id": 2}]'
items = json.loads(json_array)
print(items) # [{'id': 1}, {'id': 2}]Reading and Writing JSON Files
import json
# Write dictionary to JSON file
data = {'users': [{'name': 'Alice'}, {'name': 'Bob'}]}
with open('data.json', 'w') as f:
json.dump(data, f, indent=2)
# Read JSON file to dictionary
with open('data.json', 'r') as f:
loaded_data = json.load(f)
print(loaded_data) # {'users': [{'name': 'Alice'}, {'name': 'Bob'}]}
# Read with encoding (important for non-ASCII)
with open('data.json', 'r', encoding='utf-8') as f:
data = json.load(f)Note: Use json.dump() and json.load() for files, and json.dumps() and json.loads() for strings. The "s" stands for "string".
Handling API Responses
import json
# In real code, you'd use: import requests
# Simulated API response
api_response = '''
{
"status": "success",
"data": {
"users": [
{"id": 1, "name": "Alice", "email": "[email protected]"},
{"id": 2, "name": "Bob", "email": "[email protected]"}
],
"total": 2
}
}
'''
# Parse the response
response_data = json.loads(api_response)
# Access nested data safely
users = response_data.get('data', {}).get('users', [])
for user in users:
print(f"{user['name']}: {user['email']}")
# With requests library (common pattern):
# response = requests.get('https://api.example.com/users')
# data = response.json() # Automatically parses JSONWorking with Nested JSON
import json
nested_data = {
'company': {
'name': 'TechCorp',
'departments': {
'engineering': {
'employees': [
{'name': 'Alice', 'role': 'Lead'},
{'name': 'Bob', 'role': 'Developer'}
]
},
'sales': {
'employees': [
{'name': 'Charlie', 'role': 'Manager'}
]
}
}
}
}
# Safe nested access with get()
def safe_get(data, *keys, default=None):
"""Safely navigate nested dictionaries."""
for key in keys:
if isinstance(data, dict):
data = data.get(key, default)
else:
return default
return data
# Usage
eng_employees = safe_get(nested_data, 'company', 'departments', 'engineering', 'employees', default=[])
print(eng_employees)
# [{'name': 'Alice', 'role': 'Lead'}, {'name': 'Bob', 'role': 'Developer'}]
# Get non-existent path safely
hr_employees = safe_get(nested_data, 'company', 'departments', 'hr', 'employees', default=[])
print(hr_employees) # []Common JSON Errors and Solutions
JSONDecodeError: Invalid JSON
# Problem: Single quotes instead of double quotes
bad_json = "{'name': 'Alice'}" # Invalid!
# json.loads(bad_json) # JSONDecodeError
# Solution: Use double quotes
good_json = '{"name": "Alice"}'
data = json.loads(good_json) # Works!TypeError: Object not serializable
from datetime import datetime
# Problem: datetime not JSON serializable
data = {'created': datetime.now()}
# json.dumps(data) # TypeError!
# Solution 1: Convert to string
data = {'created': datetime.now().isoformat()}
# Solution 2: Custom encoder
class DateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
return super().default(obj)
json.dumps({'created': datetime.now()}, cls=DateTimeEncoder)Trailing Commas
# Problem: Trailing comma (valid in Python, invalid in JSON)
bad_json = '{"name": "Alice", "age": 30,}' # Invalid!
# Solution: Remove trailing comma
good_json = '{"name": "Alice", "age": 30}'Best Practices
Always use encoding='utf-8' when reading/writing files
Prevents encoding issues with special characters
Use .get() for safe access to potentially missing keys
Avoids KeyError exceptions with unknown JSON structure
Validate JSON before processing
Use try/except to handle malformed JSON gracefully
Use indent=2 for human-readable output
Makes debugging and logging much easier
On This Page
- Introduction
- Dict to JSON
- JSON to Dict
- File Operations
- API Responses
- Nested JSON
- Common Errors
- Best Practices
Related Content
- Real-World Examples
Practical dictionary patterns in production code
- Best Practices
Coding standards for effective dictionary usage
- FAQ
Common Python dictionary questions answered