Python JSON Files
Introduction
JSON (JavaScript Object Notation) is a lightweight data format that has become extremely popular for data exchange between applications. Despite its origins in JavaScript, JSON is language-independent and Python provides excellent support for working with JSON data through its built-in json
module.
In this tutorial, you'll learn:
- What JSON is and why it's important
- How to convert Python objects to JSON (serialization)
- How to convert JSON back to Python objects (deserialization)
- How to read and write JSON files
- How to handle complex data and formatting
What is JSON?
JSON is a text-based data format that's easy for humans to read and write, and easy for machines to parse and generate. It's built on two structures:
- A collection of key-value pairs (similar to Python dictionaries)
- An ordered list of values (similar to Python lists)
Here's a simple JSON example:
{
"name": "John",
"age": 30,
"city": "New York",
"languages": ["Python", "JavaScript", "SQL"],
"is_programmer": true,
"hobbies": null
}
JSON supports these data types:
- Strings:
"Hello, World!"
- Numbers:
42
,3.14
- Booleans:
true
,false
- Arrays:
[1, 2, 3]
- Objects:
{"name": "John"}
- Null:
null
The Python json
Module
Python's built-in json
module provides functionality to encode Python objects as JSON strings and decode JSON strings back into Python objects.
Let's first import the module:
import json
Converting Python Objects to JSON (Serialization)
The process of converting Python objects to JSON format is called serialization (or encoding). We use the json.dumps()
function for this.
# Python dictionary
person = {
"name": "Alice",
"age": 25,
"city": "Boston",
"languages": ["Python", "Java"],
"is_student": True,
"grades": None
}
# Convert to JSON string
json_string = json.dumps(person)
print(json_string)
Output:
{"name": "Alice", "age": 25, "city": "Boston", "languages": ["Python", "Java"], "is_student": true, "grades": null}
Notice how Python's True
became true
and None
became null
in the JSON output.
Making JSON Output More Readable
You can make the JSON output more readable by adding indentation:
# Pretty printing with indentation
formatted_json = json.dumps(person, indent=2)
print(formatted_json)
Output:
{
"name": "Alice",
"age": 25,
"city": "Boston",
"languages": [
"Python",
"Java"
],
"is_student": true,
"grades": null
}
Additional Formatting Options
The json.dumps()
function provides several parameters to customize the output:
# Sort keys and add indentation
json_string = json.dumps(person, indent=4, sort_keys=True)
print(json_string)
Output:
{
"age": 25,
"city": "Boston",
"grades": null,
"is_student": true,
"languages": [
"Python",
"Java"
],
"name": "Alice"
}
Converting JSON to Python Objects (Deserialization)
To convert JSON strings back to Python objects, use the json.loads()
function:
# JSON string
json_data = '{"name": "Bob", "age": 30, "city": "New York"}'
# Parse JSON string to Python dictionary
parsed_data = json.loads(json_data)
print(parsed_data)
print(type(parsed_data))
print(f"Name: {parsed_data['name']}")
Output:
{'name': 'Bob', 'age': 30, 'city': 'New York'}
<class 'dict'>
Name: Bob
Reading and Writing JSON Files
Writing JSON to a File
To save JSON data to a file, use the json.dump()
function:
# Python dictionary to save
user_data = {
"users": [
{"id": 1, "name": "John", "active": True},
{"id": 2, "name": "Sara", "active": False},
{"id": 3, "name": "Mike", "active": True}
],
"total": 3,
"page": 1
}
# Writing to a JSON file
with open('users.json', 'w') as file:
json.dump(user_data, file, indent=4)
print("Data successfully written to users.json")
Output:
Data successfully written to users.json
This creates a file called users.json
in your current directory with the formatted JSON data.
Reading JSON from a File
To read JSON data from a file, use the json.load()
function:
# Reading from a JSON file
with open('users.json', 'r') as file:
loaded_data = json.load(file)
print("Data loaded from file:")
print(f"Total users: {loaded_data['total']}")
print("User names:")
for user in loaded_data['users']:
print(f"- {user['name']} (Active: {user['active']})")
Output:
Data loaded from file:
Total users: 3
User names:
- John (Active: True)
- Sara (Active: False)
- Mike (Active: True)
Working with Complex Data Types
Handling Dates and Custom Objects
JSON doesn't natively support dates or custom Python objects. To handle these, we need custom encoding/decoding.
from datetime import datetime
# Dictionary with a datetime object
event = {
"name": "Python Workshop",
"date": datetime.now(),
"attendees": 150
}
# This will raise a TypeError
try:
json_string = json.dumps(event)
except TypeError as e:
print(f"Error: {e}")
# Solution: Create a custom encoder
def datetime_to_str(obj):
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError("Type not serializable")
# Now it works
json_string = json.dumps(event, default=datetime_to_str, indent=2)
print(json_string)
Output:
Error: Object of type datetime is not JSON serializable
{
"name": "Python Workshop",
"date": "2023-07-21T14:30:45.123456",
"attendees": 150
}
Custom JSON Encoder
For more complex serialization needs, you can create a custom JSON encoder by subclassing json.JSONEncoder
:
class CustomEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
elif hasattr(obj, 'to_json'):
return obj.to_json()
return super().default(obj)
# Example class with to_json method
class Product:
def __init__(self, id, name, price):
self.id = id
self.name = name
self.price = price
def to_json(self):
return {
"id": self.id,
"name": self.name,
"price": self.price
}
# Complex data with custom objects and dates
data = {
"product": Product(1, "Laptop", 999.99),
"created_at": datetime.now()
}
# Use the custom encoder
json_string = json.dumps(data, cls=CustomEncoder, indent=2)
print(json_string)
Output:
{
"product": {
"id": 1,
"name": "Laptop",
"price": 999.99
},
"created_at": "2023-07-21T14:32:10.987654"
}
Real-World Application: Weather Data
Let's create a practical example where we fetch weather data from a file and analyze it:
# Sample weather data
weather_data = {
"city": "San Francisco",
"days": [
{"date": "2023-07-15", "temperature": 18, "humidity": 85, "conditions": "Cloudy"},
{"date": "2023-07-16", "temperature": 22, "humidity": 70, "conditions": "Sunny"},
{"date": "2023-07-17", "temperature": 20, "humidity": 75, "conditions": "Partly Cloudy"},
{"date": "2023-07-18", "temperature": 21, "humidity": 80, "conditions": "Foggy"},
{"date": "2023-07-19", "temperature": 23, "humidity": 65, "conditions": "Sunny"}
]
}
# Save to file
with open('weather.json', 'w') as file:
json.dump(weather_data, file, indent=2)
print("Weather data saved to weather.json")
# Now let's read and analyze the data
with open('weather.json', 'r') as file:
weather = json.load(file)
# Calculate average temperature
temps = [day["temperature"] for day in weather["days"]]
avg_temp = sum(temps) / len(temps)
# Find the hottest day
hottest_day = max(weather["days"], key=lambda day: day["temperature"])
print(f"Weather analysis for {weather['city']}:")
print(f"Average temperature: {avg_temp:.1f}°C")
print(f"Hottest day: {hottest_day['date']} with {hottest_day['temperature']}°C ({hottest_day['conditions']})")
Output:
Weather data saved to weather.json
Weather analysis for San Francisco:
Average temperature: 20.8°C
Hottest day: 2023-07-19 with 23°C (Sunny)
Common Errors and How to Handle Them
1. Invalid JSON Format
try:
# Invalid JSON (missing quotation marks around keys)
bad_json = '{name: "John", age: 30}'
parsed = json.loads(bad_json)
except json.JSONDecodeError as e:
print(f"JSON parsing error: {e}")
Output:
JSON parsing error: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
2. File Not Found
try:
with open('nonexistent_file.json', 'r') as file:
data = json.load(file)
except FileNotFoundError:
print("Error: The specified file was not found.")
Output:
Error: The specified file was not found.
Summary
In this tutorial, you've learned:
- What JSON is: A lightweight, text-based data format used for data exchange
- Serialization: Converting Python objects to JSON using
json.dumps()
andjson.dump()
- Deserialization: Converting JSON to Python objects using
json.loads()
andjson.load()
- File Operations: Reading and writing JSON files
- Handling Complex Types: Using custom encoders for datetime and custom objects
- Real-world Applications: Working with structured data like weather information
- Error Handling: Dealing with common JSON-related errors
JSON is an essential skill for any Python developer, especially if you're working with APIs, configuration files, or data exchange between systems.
Additional Exercises
-
Create a program that reads a JSON file containing a list of books, and allows users to add new books, search for books by title or author, and save changes back to the file.
-
Write a script that converts a CSV file to JSON format, handling different data types appropriately.
-
Create a simple address book application that stores contacts in a JSON file, with functions to add, edit, delete, and search for contacts.
-
Modify the weather data example to analyze more aspects, such as the most common weather condition or the day with the highest humidity.
Additional Resources
- Python JSON Documentation
- JSON.org - Official JSON website with specifications
- JSONLint - Online JSON validator
Happy coding with JSON in Python!
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)