Fixing 'TypeError: Object of type datetime is not JSON serializable' in Python

beginner🐍 Python2026-06-18| Python 3.8+, Linux, macOS, Windows

Error Message

TypeError: Object of type datetime is not JSON serializable
#python#json#datetime#serialization#json.dumps

The ProblemTrying to dump a Python dictionary into a JSON string only to have your program crash is a common rite of passage for developers. You use the standard json.dumps() method, but instead of a clean string, you get a stack trace:

TypeError: Object of type datetime is not JSON serializable

The error usually hits right when you are sending data to an API or saving records to a disk. You'll most likely encounter this wall when fetching rows from PostgreSQL, MySQL, or MongoDB, where timestamp columns are automatically converted into Python datetime objects.

Example Code that Triggers the Error```

import json from datetime import datetime

data = { "id": 1024, "event": "User Signup", "timestamp": datetime.now() # This object causes the crash }

This line raises the TypeError

json_data = json.dumps(data)


## Why This HappensPython's built-in `json` module is efficient but picky. By default, it only understands how to map basic types that have a direct JSON equivalent, such as strings, integers, floats, and booleans. JSON itself has no native 'Date' type. Since the specification doesn't define if a date should be a string or a number, Python refuses to make a guess for you. It simply stops the process.
## How to Fix It### Method 1: The Quick Fix (The 'default' Argument)For small scripts, pass a function to the `default` parameter in `json.dumps()`. This tells the encoder what to do when it hits an object it doesn't recognize.

import json from datetime import datetime

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

Force any non-serializable object into a string

json_data = json.dumps(data, default=str)

print(json_data)

Output: {"timestamp": "2024-06-17 14:30:05.123456"}


While `default=str` is fast, it's a bit of a blunt instrument. You might prefer a more standardized format like ISO 8601.
### Method 2: Custom JSON Encoder (Recommended for Production)If you're building a larger application, a reusable encoder class is the way to go. It keeps your serialization logic in one place and ensures consistency across your entire API.

import json from datetime import datetime, date

class DateTimeEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, (datetime, date)): return obj.isoformat() return super().default(obj)

data = { "created_at": datetime.now(), "is_active": True }

Use the 'cls' argument to use your custom logic

json_data = json.dumps(data, cls=DateTimeEncoder)

print(json_data)


### Method 3: Pre-processing DataSometimes you don't want to change how the encoder works. Instead, you can manually transform the dictionary before passing it to the dump function. This is often safer when you only have one or two date fields.

from datetime import datetime import json

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

Create a shallow copy and format the specific field

clean_data = {**data, "last_login": data["last_login"].strftime('%Y-%m-%d %H:%M:%S')}

json_output = json.dumps(clean_data)


### Method 4: Using Pydantic (Modern Python)If you use FastAPI or modern data validation, you likely already have **Pydantic** installed. It handles complex serialization out of the box without any extra configuration.

from pydantic import BaseModel from datetime import datetime

class Event(BaseModel): name: str timestamp: datetime

event = Event(name="System Update", timestamp=datetime.now())

Pydantic v2 uses model_dump_json()

print(event.model_dump_json())


## Verification StepsOnce you've applied a fix, run these checks to ensure your data is actually usable:
- Confirm the script finishes without raising a `TypeError`.- Ensure the output date string looks like `"2024-06-17T10:00:00"` rather than a raw object string.- Verify the JSON is valid by attempting to load it back:```
try:
    json.loads(json_data)
    print("JSON is valid and ready for use.")
except Exception as e:
    print(f"Verification failed: {e}")

Prevention and Tips- Standardize on ISO 8601: Use obj.isoformat(). It's the industry standard that JavaScript, React, and mobile apps can parse instantly.- Adopt UTC: Avoid timezone bugs by using datetime.now(timezone.utc). Note that utcnow() is deprecated starting in Python 3.12.When I'm debugging complex JSON structures that contain nested dates, I often use the JSON Formatter at ToolCraft to make sure the structure is correct. If you're dealing with Unix timestamps instead of strings, their Timestamp Converter is very handy for checking if your numbers actually point to the correct date. Both tools run entirely in your browser, which is great for privacy.

Related Error Notes