What is JSON?

JSON (JavaScript Object Notation) is the most common data format for exchanging information between systems. APIs return JSON, config files use JSON, and databases store JSON. If you work with any external data, you'll work with JSON.

{
    "name": "Alice",
    "age": 25,
    "is_admin": false,
    "skills": ["Python", "Linux", "Security"],
    "address": {
        "city": "London",
        "country": "UK"
    }
}
💡
JSON ↔ Python mapping

JSON objects become Python dicts, JSON arrays become lists, true/false become True/False, and null becomes None.

Parsing JSON Strings

import json

# JSON string → Python dict
json_string = '{"name": "Alice", "age": 25, "active": true}'
data = json.loads(json_string)

print(data["name"])        # Alice
print(data["age"])         # 25
print(type(data))          # <class 'dict'>

# Python dict → JSON string
user = {"name": "Bob", "age": 30, "active": True}
json_output = json.dumps(user)
print(json_output)         # {"name": "Bob", "age": 30, "active": true}

# Pretty-print JSON
print(json.dumps(user, indent=2))
# {
#   "name": "Bob",
#   "age": 30,
#   "active": true
# }

Reading JSON Files

import json

# Read a JSON file
with open("config.json", "r") as file:
    config = json.load(file)         # Note: load (not loads)

print(config["database"]["host"])
print(config["debug"])

Writing JSON Files

import json

data = {
    "users": [
        {"name": "Alice", "role": "admin"},
        {"name": "Bob", "role": "user"}
    ],
    "version": "1.0",
    "last_updated": "2026-03-04"
}

# Write to file (pretty-printed)
with open("data.json", "w") as file:
    json.dump(data, file, indent=2)    # Note: dump (not dumps)
💡
loads/dumps vs load/dump

loads/dumps work with strings (the "s" stands for string). load/dump work with files.

Handling JSON Errors

import json

# Invalid JSON will raise JSONDecodeError
bad_json = '{"name": "Alice", age: 25}'    # Missing quotes around key

try:
    data = json.loads(bad_json)
except json.JSONDecodeError as e:
    print(f"Invalid JSON: {e}")
    # Invalid JSON: Expecting property name enclosed in double quotes

Working with Nested JSON

import json

response = '''
{
    "status": "success",
    "data": {
        "users": [
            {"id": 1, "name": "Alice", "email": "alice@example.com"},
            {"id": 2, "name": "Bob", "email": "bob@example.com"}
        ],
        "total": 2
    }
}
'''

data = json.loads(response)

# Access nested values
print(data["status"])                      # success
print(data["data"]["total"])               # 2

# Loop through nested arrays
for user in data["data"]["users"]:
    print(f"{user['name']}: {user['email']}")

# Safe access with .get() (avoids KeyError)
phone = data["data"]["users"][0].get("phone", "Not provided")
print(phone)    # Not provided

Practical Examples

Config File Manager

import json
from pathlib import Path

class Config:
    def __init__(self, filename):
        self.filename = filename
        self.data = {}
        self._load()

    def _load(self):
        path = Path(self.filename)
        if path.exists():
            with open(self.filename, "r") as f:
                self.data = json.load(f)

    def save(self):
        with open(self.filename, "w") as f:
            json.dump(self.data, f, indent=2)

    def get(self, key, default=None):
        return self.data.get(key, default)

    def set(self, key, value):
        self.data[key] = value
        self.save()

# Usage
config = Config("app_settings.json")
config.set("theme", "dark")
config.set("language", "en")
config.set("notifications", True)
print(config.get("theme"))         # dark

Log Analyzer

import json

# Parse JSON log entries
log_entries = [
    '{"timestamp": "2026-03-04T10:30:00", "level": "INFO", "message": "Server started"}',
    '{"timestamp": "2026-03-04T10:30:05", "level": "ERROR", "message": "Database timeout"}',
    '{"timestamp": "2026-03-04T10:30:10", "level": "INFO", "message": "Retry successful"}',
    '{"timestamp": "2026-03-04T10:31:00", "level": "ERROR", "message": "Disk space low"}'
]

errors = []
for entry_str in log_entries:
    entry = json.loads(entry_str)
    if entry["level"] == "ERROR":
        errors.append(entry)

print(f"Found {len(errors)} errors:")
for error in errors:
    print(f"  [{error['timestamp']}] {error['message']}")

Data Transformation

import json

# Transform JSON data between formats
api_response = '''
[
    {"first_name": "Alice", "last_name": "Smith", "age": 25},
    {"first_name": "Bob", "last_name": "Jones", "age": 30}
]
'''

users = json.loads(api_response)

# Transform to a different format
transformed = {
    user["first_name"].lower(): {
        "full_name": f"{user['first_name']} {user['last_name']}",
        "age": user["age"]
    }
    for user in users
}

print(json.dumps(transformed, indent=2))
# {
#   "alice": {"full_name": "Alice Smith", "age": 25},
#   "bob": {"full_name": "Bob Jones", "age": 30}
# }

JSON Serialization Tips

import json
from datetime import datetime

# Problem: datetime is not JSON serializable
data = {"timestamp": datetime.now()}
# json.dumps(data)   # TypeError!

# Solution: custom serializer
def json_serial(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    raise TypeError(f"Type {type(obj)} not serializable")

json_output = json.dumps(data, default=json_serial)
print(json_output)    # {"timestamp": "2026-03-04T10:30:00.000000"}

# Other useful dumps options
json.dumps(data, default=json_serial,
           indent=2,              # Pretty print
           sort_keys=True,        # Alphabetical keys
           ensure_ascii=False)    # Allow unicode characters

Summary

  • json.loads(string) parses a JSON string into Python objects
  • json.dumps(obj) converts Python objects to a JSON string
  • json.load(file) reads JSON from a file
  • json.dump(obj, file) writes JSON to a file
  • Use indent=2 for human-readable output
  • Use .get(key, default) for safe access to nested data
  • Handle json.JSONDecodeError for invalid JSON input
🎉
JSON mastered!

You can now exchange data with APIs, save configurations, and process structured data. Next up: regular expressions — powerful pattern matching for text processing.