What is JSON in Python?

Learn how to use the json module in Python to read, write, and manipulate JSON data. Practical examples, best practices, and comprehensive FAQ.
8 min read
Believemy logo

Definition of JSON in Python

JSON, which stands for JavaScript Object Notation, is a lightweight and human-readable data exchange format. In Python, the built-in json module allows you to serialize (convert Python objects to JSON strings) and deserialize (convert JSON strings to Python objects) data with remarkable simplicity.

If you want to master Python as a whole, including JSON data manipulation, we recommend following our complete Python course which covers this topic in depth.

The JSON format has become an essential standard in modern web development. It is used for REST APIs, configuration files, data storage, and much more. Python, thanks to its native json module, offers seamless integration with this format.

 

JSON data types and their Python counterparts

Before diving into examples, it is essential to understand how JSON types are mapped to Python types and vice versa. This mapping is automatic when you use the json module.

JSON TypePython TypeJSON ExamplePython Example
objectdict{"name": "Alice"}{'name': 'Alice'}
arraylist[1, 2, 3][1, 2, 3]
stringstr"hello"'hello'
number (int)int4242
number (float)float3.143.14
true / falsebooltrueTrue
nullNonenullNone
Good to know

The json module is part of Python's standard library. You don't need to install anything: a simple import json is all you need to start working with this format.

 

Main functions of the json module

The json module provides four main functions that you will use on a daily basis. They are divided into two pairs: one for working with strings, the other for working directly with files.

FunctionDirectionSource / Destination
json.dumps()Python → JSONString
json.loads()JSON → PythonString
json.dump()Python → JSONFile
json.load()JSON → PythonFile
Good to know

Mnemonic tip: the "s" at the end of dumps and loads stands for "string". These functions work with strings, while dump and load (without the "s") work with files.

 

Practical examples

Serializing a Python object to JSON (dumps)

The json.dumps() function converts a Python object into a JSON string. This is the most common operation when you need to send data to an API or store it as text.

PYTHON
import json

# Creating a Python dictionary
user = {
    "name": "Alice Dupont",
    "age": 30,
    "email": "alice@example.com",
    "languages": ["Python", "JavaScript", "Rust"],
    "active": True,
    "address": {
        "city": "Paris",
        "zip_code": "75001"
    }
}

# Converting to a JSON string
json_string = json.dumps(user)
print(json_string)
# {"name": "Alice Dupont", "age": 30, "email": "alice@example.com", ...}

# With readable formatting (indentation)
json_formatted = json.dumps(user, indent=4, ensure_ascii=False)
print(json_formatted)

The indent=4 parameter adds 4-space indentation to make the JSON readable. The ensure_ascii=False parameter preserves special characters like accents instead of encoding them as Unicode escape sequences.

 

Deserializing a JSON string to a Python object (loads)

The json.loads() function performs the reverse operation: it transforms a JSON string into a native Python object.

PYTHON
import json

# JSON string received (for example from an API)
json_data = '''
{
    "product": "Laptop",
    "price": 999.99,
    "in_stock": true,
    "features": ["16 GB RAM", "512 GB SSD", "15-inch screen"],
    "promotion": null
}
'''

# Converting to a Python dictionary
product = json.loads(json_data)

print(type(product))        # 
print(product["product"])    # Laptop
print(product["price"])      # 999.99
print(product["in_stock"])   # True (Python boolean)
print(product["promotion"])  # None (not "null")

# Accessing list elements
for feature in product["features"]:
    print(f"- {feature}")

Notice how true in JSON is automatically converted to True in Python, and null becomes None. This conversion is entirely transparent.

 

Reading and writing JSON files

In most real-world cases, you will work with JSON files rather than strings. The json.dump() and json.load() functions are designed for this purpose.

PYTHON
import json

# === WRITING to a JSON file ===
config = {
    "application": "MyApp",
    "version": "2.1.0",
    "debug": False,
    "database": {
        "host": "localhost",
        "port": 5432,
        "name": "my_database"
    },
    "supported_languages": ["fr", "en", "es"]
}

with open("config.json", "w", encoding="utf-8") as file:
    json.dump(config, file, indent=4, ensure_ascii=False)

print("config.json file created successfully!")

# === READING from a JSON file ===
with open("config.json", "r", encoding="utf-8") as file:
    config_read = json.load(file)

print(config_read["application"])  # MyApp
print(config_read["database"]["port"])  # 5432
Warning

Always use encoding="utf-8" when opening JSON files to avoid encoding issues, especially on Windows where the default encoding may differ.

 

Handling JSON parsing errors

When processing JSON data from external sources (APIs, user files, etc.), it is imperative to handle potential errors. The json module raises a json.JSONDecodeError exception if the JSON is malformed.

PYTHON
import json

# Invalid JSON (trailing comma)
invalid_json = '{"name": "Alice", "age": 30,}'

try:
    data = json.loads(invalid_json)
except json.JSONDecodeError as e:
    print(f"JSON parsing error: {e}")
    print(f"Error position: line {e.lineno}, column {e.colno}")

# Handling a missing or corrupted JSON file
try:
    with open("data.json", "r", encoding="utf-8") as f:
        data = json.load(f)
except FileNotFoundError:
    print("The file does not exist")
    data = {}  # Default value
except json.JSONDecodeError as e:
    print(f"The file contains invalid JSON: {e}")
    data = {}

 

Serializing custom objects

By default, the json module does not know how to serialize objects from your custom classes. You need to provide a custom encoder or a conversion function.

PYTHON
import json
from datetime import datetime, date


# Method 1: Using the 'default' parameter
def custom_converter(obj):
    """Converts non-serializable objects to JSON-compatible types."""
    if isinstance(obj, (datetime, date)):
        return obj.isoformat()
    if isinstance(obj, set):
        return list(obj)
    raise TypeError(f"Object of type {type(obj)} is not serializable")

event = {
    "title": "Python Conference",
    "date": datetime(2025, 6, 15, 14, 30),
    "tags": {"python", "development", "conference"}
}

json_result = json.dumps(
    event,
    default=custom_converter,
    indent=2,
    ensure_ascii=False
)
print(json_result)


# Method 2: Creating a custom JSONEncoder
class MyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        if isinstance(obj, set):
            return sorted(list(obj))
        return super().default(obj)

json_result2 = json.dumps(event, cls=MyEncoder, indent=2, ensure_ascii=False)
print(json_result2)

Both methods are valid. The default parameter is simpler for one-off cases, while creating a custom JSONEncoder is preferable when you have reusable serialization logic throughout your project.

 

Advanced dumps parameters

The json.dumps() function offers many parameters to finely control the JSON output.

PYTHON
import json

data = {
    "name": "Alice",
    "scores": [95, 87, 92],
    "address": {"city": "Lyon", "country": "France"}
}

# Sort keys alphabetically
print(json.dumps(data, sort_keys=True, indent=2))

# Customize separators for compact JSON
print(json.dumps(data, separators=(',', ':')))
# {"name":"Alice","scores":[95,87,92],"address":{"city":"Lyon","country":"France"}}

# Combining parameters for optimal output
optimized_json = json.dumps(
    data,
    indent=2,
    ensure_ascii=False,
    sort_keys=True,
    separators=(',', ': ')
)
print(optimized_json)

The separators parameter allows you to control spacing in the generated JSON. By using (',', ':') without spaces, you produce compact JSON ideal for network transfer, where every byte counts.

 

Using json with complex and nested data

In practice, you will often encounter complex JSON structures with multiple levels of nesting. Here is how to manipulate them efficiently.

PYTHON
import json

# Typical API response
api_response = '''
{
    "status": "success",
    "total": 2,
    "users": [
        {
            "id": 1,
            "name": "Alice Dupont",
            "skills": ["Python", "Django"],
            "projects": [
                {"name": "REST API", "completed": true},
                {"name": "Discord Bot", "completed": false}
            ]
        },
        {
            "id": 2,
            "name": "Bob Martin",
            "skills": ["Python", "Flask"],
            "projects": [
                {"name": "Website", "completed": true}
            ]
        }
    ]
}
'''

data = json.loads(api_response)

# Navigating through nested data
for user in data["users"]:
    print(f"\n{user['name']}:")
    print(f"  Skills: {', '.join(user['skills'])}")
    for project in user["projects"]:
        status = "✅" if project["completed"] else "⏳"
        print(f"  {status} {project['name']}")

 

Best practices

To use the json module effectively in Python, here are the best practices we recommend:

  • Always use ensure_ascii=False if your data contains non-ASCII characters (accents, special characters). This produces more readable and often more compact JSON.
  • Systematically handle json.JSONDecodeError exceptions when deserializing data from external sources. Never trust unvalidated JSON.
  • Use indent for debugging and storage, but remove it for network transfer. Compact JSON reduces bandwidth usage.
  • Prefer encoding="utf-8" when opening any JSON file to ensure cross-platform compatibility.
  • Use json.dumps() with sort_keys=True if you need deterministic results (useful for comparisons, hashing, or versioning).
  • Never store sensitive data (passwords, tokens) in plain text JSON files. Use environment variables or secret management solutions.
  • Use dict to structure your data before serialization. The correspondence between Python dictionaries and JSON objects is direct and natural.
  • Consider using dataclass to model structured data before converting it to JSON. They offer better readability and implicit type validation.
Warning

Python's json module does not natively handle comments in JSON files. If you need configuration files with comments, consider the TOML format (natively supported since Python 3.11) or YAML.

 

Frequently asked questions

Question

What is the difference between json.dumps() and json.dump()?

json.dumps() (with an "s" for "string") converts a Python object into a JSON string that you can store in a variable or manipulate in memory. json.dump() (without the "s") writes JSON directly to an open file. The rule is simple: use dumps/loads for strings and dump/load for files.

 

Question

Can you serialize tuples and sets to JSON?

tuple are automatically converted to JSON arrays during serialization, just like list. However, set are not directly serializable and will raise a TypeError. To serialize them, you need to convert them to lists, either manually or by using a custom encoder with the default parameter of json.dumps().

 

Question

Is the json module suitable for very large files?

The standard json module loads the entire file into memory, which can be problematic for files of several gigabytes. For these use cases, consider libraries like ijson (incremental parsing), orjson, or ujson (faster alternatives). For most common uses (configuration files, API responses), the standard module is perfectly adequate and performant enough.

 

Question

How can I learn to master JSON and Python in depth?

JSON manipulation is a fundamental skill for every Python developer, whether it's for consuming APIs, managing configurations, or exchanging data. To master this topic along with the entire Python ecosystem, we recommend following our dedicated Python course on Believemy. You will learn not only JSON manipulation but also all the skills needed to become an accomplished Python developer.

Related terms

Discover our python glossary

Browse the terms and definitions most commonly used in development with Python.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.