Python JSON

Learn how to work with JSON data in Python using the json module for parsing and generating JSON.

JSON in Python

JSON is a syntax for storing and exchanging data.

JSON is text, written with JavaScript object notation.

Python has a built-in package called json, which can be used to work with JSON data.

Example - Import the json module:

import json

Parse JSON - Convert from JSON to Python

If you have a JSON string, you can parse it by using the json.loads() method.

The result will be a Python dictionary.

Example - Convert from JSON to Python:

import json

# some JSON:
x = '{ "name":"John", "age":30, "city":"New York"}'

# parse x:
y = json.loads(x)

# the result is a Python dictionary:
print(y["age"])

Convert from Python to JSON

If you have a Python object, you can convert it into a JSON string by using the json.dumps() method.

Example - Convert from Python to JSON:

import json

# a Python object (dict):
x = {
  "name": "John",
  "age": 30,
  "city": "New York"
}

# convert into JSON:
y = json.dumps(x)

# the result is a JSON string:
print(y)

Convert Python objects into JSON strings

You can convert Python objects of the following types, into JSON strings:

  • dict
  • list
  • tuple
  • string
  • int
  • float
  • True
  • False
  • None

Example - Convert Python objects into JSON strings:

import json

print(json.dumps({"name": "John", "age": 30}))
print(json.dumps(["apple", "bananas"]))
print(json.dumps(("apple", "bananas")))
print(json.dumps("hello"))
print(json.dumps(42))
print(json.dumps(31.76))
print(json.dumps(True))
print(json.dumps(False))
print(json.dumps(None))

Python to JSON Conversion Table

When you convert from Python to JSON, Python objects are converted into the JSON (JavaScript) equivalent:

dict
Object
list
Array
tuple
Array
str
String
int
Number
float
Number
True
true
False
false
None
null

Format the Result

The example above prints a JSON string, but it is not very easy to read, with no indentations and line breaks.

The json.dumps() method has parameters to make it easier to read the result:

Example - Use the indent parameter to define the numbers of indents:

import json

x = {
  "name": "John",
  "age": 30,
  "married": True,
  "divorced": False,
  "children": ("Ann","Peter","James"),
  "pets": None,
  "cars": [
    {"model": "BMW 230", "mpg": 27.5},
    {"model": "Ford Edge", "mpg": 24.1}
  ]
}

print(json.dumps(x, indent=4))

You can also define the separators, default value is (", ", ": "), which means using a comma and a space to separate each object, and a colon and a space to separate keys from values:

Example - Use the separators parameter to change the default separator:

import json

x = {
  "name": "John",
  "age": 30,
  "married": True,
  "divorced": False,
  "children": ("Ann","Peter","James"),
  "pets": None,
  "cars": [
    {"model": "BMW 230", "mpg": 27.5},
    {"model": "Ford Edge", "mpg": 24.1}
  ]
}

print(json.dumps(x, indent=4, separators=(". ", " = ")))

Order the Result

The json.dumps() method has parameters to order the keys in the result:

Example - Use the sort_keys parameter to specify if the result should be sorted or not:

import json

x = {
  "name": "John",
  "age": 30,
  "married": True,
  "divorced": False,
  "children": ("Ann","Peter","James"),
  "pets": None,
  "cars": [
    {"model": "BMW 230", "mpg": 27.5},
    {"model": "Ford Edge", "mpg": 24.1}
  ]
}

print(json.dumps(x, indent=4, sort_keys=True))

Working with JSON Files

You can read and write JSON data to files using the json module:

Example - Writing JSON to a file:

import json

data = {
    "employees": [
        {"name": "John", "age": 30, "department": "IT"},
        {"name": "Jane", "age": 25, "department": "HR"},
        {"name": "Bob", "age": 35, "department": "Finance"}
    ],
    "company": "Tech Corp",
    "founded": 2010
}

# Write JSON to file
with open('data.json', 'w') as file:
    json.dump(data, file, indent=4)

print("Data written to data.json")

Example - Reading JSON from a file:

import json

# Read JSON from file
try:
    with open('data.json', 'r') as file:
        data = json.load(file)
    
    print("Company:", data['company'])
    print("Founded:", data['founded'])
    print("\nEmployees:")
    for employee in data['employees']:
        print(f"- {employee['name']}, Age: {employee['age']}, Dept: {employee['department']}")
        
except FileNotFoundError:
    print("File not found!")
except json.JSONDecodeError:
    print("Invalid JSON format!")

Handling JSON Errors

When working with JSON, you should handle potential errors:

Example - Error handling with JSON:

import json

def safe_json_parse(json_string):
    """Safely parse JSON string with error handling."""
    try:
        return json.loads(json_string)
    except json.JSONDecodeError as e:
        print(f"JSON decode error: {e}")
        return None
    except TypeError as e:
        print(f"Type error: {e}")
        return None

# Valid JSON
valid_json = '{"name": "John", "age": 30}'
result = safe_json_parse(valid_json)
print("Valid JSON result:", result)

# Invalid JSON
invalid_json = '{"name": "John", "age": 30,}'  # Extra comma
result = safe_json_parse(invalid_json)
print("Invalid JSON result:", result)

# Not a string
not_string = {"name": "John"}
result = safe_json_parse(not_string)
print("Not string result:", result)

Custom JSON Encoding

You can create custom JSON encoders for complex objects:

Example - Custom JSON encoder:

import json
from datetime import datetime, date

class DateTimeEncoder(json.JSONEncoder):
    """Custom JSON encoder for datetime objects."""
    
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        elif isinstance(obj, date):
            return obj.isoformat()
        elif hasattr(obj, '__dict__'):
            return obj.__dict__
        return super().default(obj)

class Person:
    def __init__(self, name, age, birth_date):
        self.name = name
        self.age = age
        self.birth_date = birth_date
        self.created_at = datetime.now()

# Create a person object
person = Person("John Doe", 30, date(1993, 5, 15))

# Convert to JSON using custom encoder
json_string = json.dumps(person, cls=DateTimeEncoder, indent=2)
print("Custom encoded JSON:")
print(json_string)

# Parse it back
parsed_data = json.loads(json_string)
print("\nParsed data:")
print(parsed_data)

Working with Nested JSON

Handle complex nested JSON structures:

Example - Nested JSON operations:

import json

# Complex nested JSON
nested_data = {
    "users": [
        {
            "id": 1,
            "name": "John Doe",
            "contact": {
                "email": "john@example.com",
                "phone": "+1-555-0123",
                "address": {
                    "street": "123 Main St",
                    "city": "New York",
                    "country": "USA"
                }
            },
            "preferences": {
                "theme": "dark",
                "notifications": True,
                "languages": ["en", "es"]
            }
        },
        {
            "id": 2,
            "name": "Jane Smith",
            "contact": {
                "email": "jane@example.com",
                "phone": "+1-555-0456",
                "address": {
                    "street": "456 Oak Ave",
                    "city": "Los Angeles",
                    "country": "USA"
                }
            },
            "preferences": {
                "theme": "light",
                "notifications": False,
                "languages": ["en"]
            }
        }
    ],
    "metadata": {
        "total_users": 2,
        "last_updated": "2023-12-07T10:30:00Z"
    }
}

def find_user_by_id(data, user_id):
    """Find a user by ID in nested JSON."""
    for user in data.get("users", []):
        if user.get("id") == user_id:
            return user
    return None

def get_user_city(data, user_id):
    """Get user's city from nested structure."""
    user = find_user_by_id(data, user_id)
    if user:
        return user.get("contact", {}).get("address", {}).get("city")
    return None

def update_user_preference(data, user_id, preference_key, value):
    """Update a user's preference."""
    user = find_user_by_id(data, user_id)
    if user:
        user.setdefault("preferences", {})[preference_key] = value
        return True
    return False

# Usage examples
print("User 1 city:", get_user_city(nested_data, 1))
print("User 2 city:", get_user_city(nested_data, 2))

# Update preference
update_user_preference(nested_data, 1, "theme", "light")
print("Updated user 1 theme:", nested_data["users"][0]["preferences"]["theme"])

# Pretty print the entire structure
print("\nComplete data structure:")
print(json.dumps(nested_data, indent=2))

JSON Schema Validation

Validate JSON data against a schema (requires jsonschema package):

Example - JSON schema validation:

# Note: This requires 'pip install jsonschema'
# For demonstration purposes only

import json

# Define a simple schema
user_schema = {
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "age": {"type": "number", "minimum": 0},
        "email": {"type": "string", "format": "email"}
    },
    "required": ["name", "age"]
}

def validate_user_data(data):
    """Simple validation without external library."""
    errors = []
    
    if not isinstance(data, dict):
        errors.append("Data must be an object")
        return errors
    
    # Check required fields
    if "name" not in data:
        errors.append("Missing required field: name")
    elif not isinstance(data["name"], str):
        errors.append("Name must be a string")
    
    if "age" not in data:
        errors.append("Missing required field: age")
    elif not isinstance(data["age"], (int, float)) or data["age"] < 0:
        errors.append("Age must be a non-negative number")
    
    # Check optional email
    if "email" in data and not isinstance(data["email"], str):
        errors.append("Email must be a string")
    
    return errors

# Test data
valid_user = {"name": "John Doe", "age": 30, "email": "john@example.com"}
invalid_user = {"name": 123, "age": -5}

print("Validating valid user:")
errors = validate_user_data(valid_user)
if errors:
    print("Errors:", errors)
else:
    print("Valid!")

print("\nValidating invalid user:")
errors = validate_user_data(invalid_user)
if errors:
    print("Errors:", errors)
else:
    print("Valid!")

Practical JSON Examples

Configuration File Manager

import json
import os

class ConfigManager:
    def __init__(self, config_file="config.json"):
        self.config_file = config_file
        self.config = self.load_config()
    
    def load_config(self):
        """Load configuration from file."""
        if os.path.exists(self.config_file):
            try:
                with open(self.config_file, 'r') as file:
                    return json.load(file)
            except (json.JSONDecodeError, IOError) as e:
                print(f"Error loading config: {e}")
                return self.get_default_config()
        else:
            return self.get_default_config()
    
    def get_default_config(self):
        """Return default configuration."""
        return {
            "database": {
                "host": "localhost",
                "port": 5432,
                "name": "myapp"
            },
            "logging": {
                "level": "INFO",
                "file": "app.log"
            },
            "features": {
                "debug_mode": False,
                "cache_enabled": True
            }
        }
    
    def save_config(self):
        """Save configuration to file."""
        try:
            with open(self.config_file, 'w') as file:
                json.dump(self.config, file, indent=4)
            return True
        except IOError as e:
            print(f"Error saving config: {e}")
            return False
    
    def get(self, key_path, default=None):
        """Get configuration value using dot notation."""
        keys = key_path.split('.')
        value = self.config
        
        for key in keys:
            if isinstance(value, dict) and key in value:
                value = value[key]
            else:
                return default
        
        return value
    
    def set(self, key_path, value):
        """Set configuration value using dot notation."""
        keys = key_path.split('.')
        config = self.config
        
        for key in keys[:-1]:
            if key not in config:
                config[key] = {}
            config = config[key]
        
        config[keys[-1]] = value

# Usage example
config = ConfigManager()

print("Database host:", config.get("database.host"))
print("Debug mode:", config.get("features.debug_mode"))

# Update configuration
config.set("features.debug_mode", True)
config.set("database.port", 3306)

# Save changes
if config.save_config():
    print("Configuration saved successfully!")

print("Updated config:")
print(json.dumps(config.config, indent=2))

API Response Handler

import json
from urllib.request import urlopen
from urllib.error import URLError

class APIClient:
    def __init__(self, base_url):
        self.base_url = base_url
    
    def fetch_data(self, endpoint):
        """Fetch JSON data from API endpoint."""
        url = f"{self.base_url}/{endpoint}"
        
        try:
            with urlopen(url) as response:
                if response.status == 200:
                    data = response.read().decode('utf-8')
                    return json.loads(data)
                else:
                    print(f"HTTP Error: {response.status}")
                    return None
        except URLError as e:
            print(f"URL Error: {e}")
            return None
        except json.JSONDecodeError as e:
            print(f"JSON Decode Error: {e}")
            return None
    
    def process_user_data(self, user_data):
        """Process user data from API response."""
        if not user_data:
            return None
        
        processed = {
            "id": user_data.get("id"),
            "name": user_data.get("name", "Unknown"),
            "email": user_data.get("email", "No email"),
            "address": self.format_address(user_data.get("address", {})),
            "company": user_data.get("company", {}).get("name", "No company")
        }
        
        return processed
    
    def format_address(self, address):
        """Format address from API data."""
        if not address:
            return "No address"
        
        parts = [
            address.get("street", ""),
            address.get("city", ""),
            address.get("zipcode", "")
        ]
        
        return ", ".join(filter(None, parts))

# Example usage (would work with a real API)
# api = APIClient("https://jsonplaceholder.typicode.com")
# user_data = api.fetch_data("users/1")
# 
# if user_data:
#     processed = api.process_user_data(user_data)
#     print("Processed user data:")
#     print(json.dumps(processed, indent=2))

# Simulated API response for demonstration
simulated_response = {
    "id": 1,
    "name": "Leanne Graham",
    "email": "Sincere@april.biz",
    "address": {
        "street": "Kulas Light",
        "city": "Gwenborough",
        "zipcode": "92998-3874"
    },
    "company": {
        "name": "Romaguera-Crona"
    }
}

api = APIClient("https://example.com")
processed = api.process_user_data(simulated_response)
print("Processed user data:")
print(json.dumps(processed, indent=2))

The Four Core Functions

FunctionDirectionWorks on
json.dumpsPython → JSON stringobject → text
json.loadsJSON string → Pythontext → object
json.dumpPython → JSON fileobject → file
json.loadJSON file → Pythonfile → object

The s suffix means "string". dumps/loads work with strings; dump/load work with file objects.

Pretty Printing and Type Mapping

import json

data = {"name": "Sam", "langs": ["Python", "SQL"], "active": True}

print(json.dumps(data, indent=2, sort_keys=True))
# {
#   "active": true,
#   "langs": [ "Python", "SQL" ],
#   "name": "Sam"
# }
PythonJSON
dict / listobject / array
strstring
True / False / Nonetrue / false / null

Try It Yourself

Exercise 1: Convert the Python list [1, 2, 3] to a JSON string.

Show solution
import json
print(json.dumps([1, 2, 3]))   # [1, 2, 3]

Exercise 2: Parse the JSON text '{"x": 10}' and print the value of x.

Show solution
import json
obj = json.loads('{"x": 10}')
print(obj["x"])   # 10

Key Takeaways

  • dumps/loads for strings; dump/load for files.
  • Use indent= for readable output.
  • JSON keys are always strings; Truetrue, Nonenull.

📘 Real-World Deep Dive

<code>json</code> is the lingua franca of APIs. Knowing how to serialise dataclasses, handle datetimes, and stream big files is the difference between a 2-second parser and a 2-hour one.

Real-Life Scenario

A small HTTP-style handler that round-trips a dict through JSON, but with datetimes and dataclasses that the stdlib does not know about.

Real-Life Example

from dataclasses import dataclass, asdict, field
from datetime import datetime, timezone
import json

@dataclass
class User:
    id: int
    name: str
    joined: datetime
    roles: list[str] = field(default_factory=list)

class APIJson(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.astimezone(timezone.utc).isoformat()
        if hasattr(obj, "__dataclass_fields__"):
            return asdict(obj)
        return super().default(obj)

u = User(1, "Ada", datetime(2024, 1, 12, 9, 30, tzinfo=timezone.utc), roles=["admin"])
encoded = json.dumps(u, cls=APIJson, indent=2)
print(encoded)

decoded = json.loads(encoded)
print(json.dumps(decoded, indent=2))

Expected Output

{
  "id": 1,
  "name": "Ada",
  "joined": "2024-01-12T09:30:00+00:00",
  "roles": [
    "admin"
  ]
}

Common mistakes

  • json.dumps(datetime.now()) raises TypeError — subclass JSONEncoder explicitly.
  • json.loads returns regular dict — type information is lost. Use a typed parser (pydantic) for validation.
  • Decoding untrusted JSON without size limits is an attack vector; stream with ijson for big payloads.

🚀 Performance & Best Practices

  • orjson/ujson are 5–20× faster than stdlib; consider them on hot paths.
  • For very large files, load with for line in f: json.loads(line) instead of f.read().
  • Pretty-printing is for humans; use separators=(",", ":") for compact wire format.

🧪 Try It Yourself

  1. Add a decoder that reconstructs a User dataclass from a JSON dict.
  2. Profile stdlib json vs. orjson on a 100 MB payload.
  3. Stream-parse a 100 M-line file with ijson instead of loading it whole.

FAQ: Python JSON

Common questions about this page.

What is Python JSON?

Python JSON is a Python Tutorial lesson that explains python json in Python. Learn how to work with JSON data in Python using the json module for parsing and generating JSON. Copy the samples and run them in the Python editor. It is written for beginners who want a clear definition and working examples.

Should I run python json examples locally for better learning?

Yes. Use the browser editor on StudyGrid for a quick check, then Download the example and run it on your computer. Local runs show real errors and the real toolchain, which is one of the fastest ways to learn python json in this Python Tutorial Python lesson (Python JSON).

How do I use python json in Python?

To use python json in Python, follow the examples on this StudyGrid page. Copy a snippet, run it in the browser, then Download and run it locally for better learning. Change the values and compare the output.

What is the syntax of python json?

This Python JSON tutorial shows python json syntax with short Python examples. Use the code blocks in this lesson for the exact statements, then try them in your editor.

Python JSON example for beginners

Yes. This page includes a beginner python json example you can copy and run. It is designed for searches such as "python json for beginners", "python json example", and "how to use python json".

What are common mistakes with python json?

Common python json mistakes include wrong syntax, mixing types, and skipping practice. Work through this Python Tutorial chapter in order, run every example, and check the output before moving on.

Why should I learn python json?

Python JSON is used in real Python work. Learning python json helps you write clearer programs and continue the Python Tutorial tutorial on StudyGrid.

Is Python JSON free to learn online?

Yes. You can learn python json free on StudyGrid (studygrid.in). This chapter is part of the Python Tutorial path and includes examples, syntax, and next-step links.