JSON Serialization in Python — Complete Guide

Python's built-in json module handles the basics well, but the moment you try to serialize a datetime, a Decimal, or a custom class instance, you hit TypeError: Object of type X is not JSON serializable. This guide covers the module's core functions and exactly how to handle the types it does not support natively.

The Basics: dumps, loads, dump, load

import json

data = {"name": "Priya Sharma", "age": 29, "active": True}

# Python object -> JSON string
json_string = json.dumps(data)
print(json_string)  # '{"name": "Priya Sharma", "age": 29, "active": true}'

# JSON string -> Python object
parsed = json.loads(json_string)
print(parsed["name"])  # Priya Sharma

# Write directly to a file
with open("user.json", "w") as f:
    json.dump(data, f, indent=2)

# Read directly from a file
with open("user.json") as f:
    loaded = json.load(f)

The "Not JSON Serializable" Error

from datetime import datetime

data = {"name": "Priya", "created_at": datetime.now()}

json.dumps(data)
# TypeError: Object of type datetime is not JSON serializable

# The json module only knows how to convert: dict, list, tuple, str,
# int, float, bool, and None. Everything else needs help.

Fix 1: The default Parameter

The simplest fix — pass a function that converts unknown types to something JSON-compatible:

from datetime import datetime
from decimal import Decimal

def json_default(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    if isinstance(obj, Decimal):
        return float(obj)
    raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable")

data = {
    "name": "Priya",
    "created_at": datetime.now(),
    "balance": Decimal("1499.50")
}

print(json.dumps(data, default=json_default))
# {"name": "Priya", "created_at": "2026-07-11T14:30:00.123456", "balance": 1499.5}

Fix 2: A Custom JSONEncoder Class

For reuse across a codebase, subclass json.JSONEncoder instead of passing default everywhere:

class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        if isinstance(obj, Decimal):
            return float(obj)
        if hasattr(obj, "__dict__"):
            return obj.__dict__  # serialize simple custom class instances
        return super().default(obj)

class Order:
    def __init__(self, id, total):
        self.id = id
        self.total = total

order = Order(id=501, total=Decimal("1499.50"))
print(json.dumps(order, cls=CustomEncoder))
# {"id": 501, "total": 1499.5}

Deserializing Back into Custom Types

Deserialization is one-directional by default — dates come back as plain strings. Use object_hook to reconstruct richer types on load:

def date_hook(d):
    for key, value in d.items():
        if key.endswith("_at"):
            try:
                d[key] = datetime.fromisoformat(value)
            except (ValueError, TypeError):
                pass
    return d

json_string = '{"name": "Priya", "created_at": "2026-07-11T14:30:00"}'
result = json.loads(json_string, object_hook=date_hook)
print(type(result["created_at"]))  # <class 'datetime.datetime'>

Quick Reference: Common Type Conversions

  • datetime / date — convert with .isoformat(), parse back with datetime.fromisoformat()
  • Decimal — convert with float() or str() to avoid precision loss for currency
  • set — convert with list(); JSON has no set type
  • bytes — convert with .decode('utf-8') or base64-encode binary data
  • Enum — convert with .value or .name
  • Custom classes — implement __dict__ access or a to_dict() method used in your encoder

Frequently Asked Questions

How do I fix "Object of type X is not JSON serializable" in Python?

This error occurs when json.dumps encounters a Python object it does not know how to convert, such as datetime, Decimal, or a custom class instance. Fix it by passing a default function or a custom JSONEncoder subclass that converts the object to a JSON-compatible type like a string or number.

How do I serialize a datetime object to JSON in Python?

Convert the datetime object to an ISO 8601 string using .isoformat() before serializing, either manually or via a default function passed to json.dumps, since the json module has no built-in support for datetime objects.

Is there a free tool to validate JSON produced by Python?

Yes. Dev Brains AI JSON Formatter validates and pretty-prints JSON output from any language, including Python, directly in your browser.

Try the Free JSON Formatter

Validate and pretty-print JSON output from your Python scripts instantly. No signup, no cost.

Related articles