TypeError: Object of type datetime is not JSON serializable

Quick answer

json.dumps() was handed a value whose type has no JSON equivalent — a datetime, Decimal, set, bytes, UUID, or a custom object. The quickest fix is json.dumps(obj, default=str); for control, convert each type yourself in a default function or a custom JSONEncoder.

Which Python types convert to JSON json.dumps converts dict, list, str, int, float, bool and None directly. datetime, Decimal, set, bytes, UUID and custom classes have no JSON equivalent and raise TypeError unless a default function or custom encoder converts them. What json.dumps() can and cannot convert Converts directly ✓ dict  → object list, tuple → array str   → string int, float → number True / False → true / false None  → null Raises TypeError ✗ datetime, date Decimal set, frozenset bytes UUID, numpy types your custom class Bridge the gap with json.dumps(obj, default=...) or a custom JSONEncoder e.g. datetime → .isoformat(), Decimal → float(), set → list()
Only the left-hand types map to JSON natively; everything on the right needs a converter.

The exact error string

The traceback ends with the type that could not be converted — datetime is the most common, but the same error names Decimal, set, bytes, UUID, and your own classes:

Traceback (most recent call last):
  File "app.py", line 5, in <module>
    json.dumps(data)
TypeError: Object of type datetime is not JSON serializable

Why it happens

The json module maps a fixed set of Python types to JSON: dict → object, list/tuple → array, str → string, int/float → number, True/Falsetrue/false, and Nonenull. Anything else has no JSON representation, so json.dumps() stops and raises TypeError rather than guess how to encode it.

Cause: datetime / date

import json
from datetime import datetime

data = {"created": datetime.now()}
json.dumps(data)
# TypeError: Object of type datetime is not JSON serializable

Convert the datetime to an ISO-8601 string. The quickest one-liner uses default=str; for explicit control use isoformat() in a default function:

import json
from datetime import datetime, date

data = {"created": datetime.now()}

# Quick fix — stringify anything json can't handle
json.dumps(data, default=str)
# {"created": "2026-06-18 14:03:55.123456"}

# Explicit fix — control the format
def encode(obj):
    if isinstance(obj, (datetime, date)):
        return obj.isoformat()
    raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable")

json.dumps(data, default=encode)
# {"created": "2026-06-18T14:03:55.123456"}

Cause: Decimal

import json
from decimal import Decimal

json.dumps({"price": Decimal("19.99")})
# TypeError: Object of type Decimal is not JSON serializable

# Fix: float() (small precision risk) or str() (exact)
json.dumps({"price": Decimal("19.99")}, default=float)   # {"price": 19.99}
json.dumps({"price": Decimal("19.99")}, default=str)     # {"price": "19.99"}

Cause: set, bytes, UUID

import json
from uuid import uuid4

def encode(obj):
    if isinstance(obj, set):
        return list(obj)                 # JSON has no set type
    if isinstance(obj, bytes):
        return obj.decode("utf-8")       # or base64 for binary data
    return str(obj)                       # UUID and anything else

json.dumps({"tags": {"a", "b"}, "id": uuid4()}, default=encode)

Cause: NumPy types (np.int64, np.ndarray)

NumPy scalars and arrays are their own types — np.int64 is not a Python int, and np.ndarray is not a list — so json.dumps() rejects them. Convert scalars with .item() (or int()/float()) and arrays with .tolist():

import json
import numpy as np

data = {"count": np.int64(42), "values": np.array([1, 2, 3])}
json.dumps(data)
# TypeError: Object of type int64 is not JSON serializable

def encode(obj):
    if isinstance(obj, np.integer):
        return int(obj)
    if isinstance(obj, np.floating):
        return float(obj)
    if isinstance(obj, np.ndarray):
        return obj.tolist()
    raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable")

json.dumps(data, default=encode)
# {"count": 42, "values": [1, 2, 3]}

Cause: a custom class, dataclass, or Pydantic model

import json
from dataclasses import dataclass, asdict

@dataclass
class User:
    name: str
    age: int

user = User("Alice", 30)

json.dumps(user)                 # TypeError: Object of type User is not JSON serializable
json.dumps(asdict(user))         # {"name": "Alice", "age": 30}

# Plain class without dataclass:
json.dumps(user, default=lambda o: o.__dict__)

# Pydantic v2 model:
# json.dumps(model.model_dump())  or  model.model_dump_json()

The reusable fix: a custom JSONEncoder

When the same types appear across a codebase, subclass json.JSONEncoder once and pass it with cls= everywhere:

import json
from datetime import datetime, date
from decimal import Decimal
from uuid import UUID

class SafeEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, (datetime, date)):
            return obj.isoformat()
        if isinstance(obj, Decimal):
            return float(obj)
        if isinstance(obj, (set, frozenset)):
            return list(obj)
        if isinstance(obj, (bytes, UUID)):
            return str(obj)
        return super().default(obj)

json.dumps(data, cls=SafeEncoder)

Check your serialized output

Once json.dumps() succeeds, paste the result into the formatter to inspect and confirm it is valid JSON. Everything runs in your browser; nothing is uploaded.

JSON Formatter JSON Validator

Frequently Asked Questions

What does TypeError: Object of type datetime is not JSON serializable mean?

It means json.dumps() received a value whose Python type has no built-in JSON representation. The json module only knows how to convert dict, list, tuple, str, int, float, bool, and None. Types like datetime, Decimal, set, bytes, UUID, and custom classes are not in that list, so it raises TypeError unless you tell it how to convert them.

How do I fix Object of type datetime is not JSON serializable?

Pass a default function to json.dumps() that converts the unsupported type. For dates, json.dumps(obj, default=str) turns datetime into a string. For full control, call obj.isoformat() inside a custom default function, or subclass json.JSONEncoder and override its default() method.

Why does Decimal raise not JSON serializable?

decimal.Decimal is a separate numeric type that json does not treat as a number, so it raises TypeError. Convert it with float(value) if minor precision loss is acceptable, or str(value) to preserve the exact value. A default such as default=lambda o: float(o) handles every Decimal in one place.

How do I serialize a Python set to JSON?

JSON has no set type, so json.dumps() raises TypeError on a set. Convert it to a list first — json.dumps(list(my_set)) — or handle it in a default function. Note that converting to a list does not guarantee order, and the value deserializes back as a list, not a set.

How do I make a custom class JSON serializable?

Give json.dumps() a way to turn the object into JSON-compatible types. The simplest options are a default function returning vars(obj) or obj.__dict__, a dataclass with dataclasses.asdict(obj), or a Pydantic model with model.model_dump(). For reusable behavior, subclass json.JSONEncoder and implement default().

About the author

Pasindu Ishan is a software developer based in Sri Lanka. He builds privacy-first developer tools at JSON Dev Tools.