How can I overcome "datetime.datetime not JSON serializable"?
Categories:
Resolving 'datetime.datetime not JSON serializable' in Python

Learn why Python's datetime
objects cause JSON serialization errors and discover robust methods to convert them into JSON-compatible formats.
When working with Python and JSON, a common hurdle developers encounter is the TypeError: datetime.datetime not JSON serializable
. This error occurs because the standard json
library in Python does not inherently know how to convert datetime
objects into a JSON-compatible format. JSON, by design, supports a limited set of data types: strings, numbers, booleans, null, arrays, and objects. Python's datetime
objects, being complex objects, fall outside this native support.
Understanding the Problem
The core issue stems from the json.dumps()
function (or json.dump()
), which attempts to serialize Python objects into JSON strings. When it encounters a datetime
object, it doesn't have a predefined rule for its conversion. Unlike simple types like integers or strings, a datetime
object contains multiple components (year, month, day, hour, minute, second, microsecond, timezone info) that cannot be directly mapped to a single JSON primitive without explicit instruction.
import json
import datetime
now = datetime.datetime.now()
data = {"event_time": now, "message": "Hello"}
try:
json_output = json.dumps(data)
print(json_output)
except TypeError as e:
print(f"Error: {e}")
Demonstration of the TypeError
when serializing a datetime
object.
flowchart TD A["Python Object with datetime"] --> B{"json.dumps()"} B --> C{Is datetime JSON-compatible?} C -->|No| D["TypeError: datetime not JSON serializable"] C -->|Yes| E["JSON String Output"] D --> F["Solution: Custom Serialization"] F --> G["datetime converted to string"] G --> B
Flowchart illustrating the JSON serialization process and the point of failure for datetime
objects.
Common Solutions for Serialization
To overcome this, you need to explicitly tell the json
encoder how to handle datetime
objects. The most common and recommended approach is to convert datetime
objects into a string representation, typically an ISO 8601 formatted string, which is universally recognized and easily parsed back into a datetime
object later.
YYYY-MM-DDTHH:MM:SS.ffffff
) is highly recommended for datetime
serialization as it's unambiguous and widely supported across different programming languages and systems.Method 1: Custom JSON Encoder
The most robust and reusable way to handle datetime
objects is to create a custom JSON encoder. This allows you to define how specific types, including datetime
, should be serialized. You can then pass this custom encoder to json.dumps()
.
import json
import datetime
class DateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return obj.isoformat()
return json.JSONEncoder.default(self, obj)
now = datetime.datetime.now()
data = {"event_time": now, "message": "Hello from custom encoder"}
json_output = json.dumps(data, cls=DateTimeEncoder)
print(json_output)
Using a custom DateTimeEncoder
to serialize datetime
objects.
Method 2: Pre-processing Data
For simpler cases or when you only have a few datetime
objects, you can manually convert them to strings before passing the data to json.dumps()
. This involves iterating through your data structure and converting datetime
instances.
import json
import datetime
def convert_datetimes_to_iso(obj):
if isinstance(obj, datetime.datetime):
return obj.isoformat()
elif isinstance(obj, dict):
return {k: convert_datetimes_to_iso(v) for k, v in obj.items()}
elif isinstance(obj, list):
return [convert_datetimes_to_iso(elem) for elem in obj]
return obj
now = datetime.datetime.now()
data = {"event_time": now, "log_entries": [
{"timestamp": datetime.datetime.now(), "level": "INFO"},
{"timestamp": datetime.datetime.utcnow(), "level": "DEBUG"}
]}
processed_data = convert_datetimes_to_iso(data)
json_output = json.dumps(processed_data, indent=4)
print(json_output)
Pre-processing data to convert datetime
objects to ISO 8601 strings.
datetime
objects. datetime.datetime.now()
returns a naive datetime
object (no timezone info), while datetime.datetime.utcnow()
returns a naive UTC datetime
. For robust applications, always use timezone-aware datetime
objects, typically with pytz
or zoneinfo
(Python 3.9+).Method 3: Using a default
Function Parameter
The json.dumps()
function accepts a default
parameter, which is a function that will be called for objects that are not serializable by the default encoder. This is a quick way to handle datetime
objects without creating a full class.
import json
import datetime
def datetime_serializer(obj):
if isinstance(obj, datetime.datetime):
return obj.isoformat()
raise TypeError(f"Object of type {obj.__class__.__name__} is not JSON serializable")
now = datetime.datetime.now()
data = {"event_time": now, "status": "completed"}
json_output = json.dumps(data, default=datetime_serializer)
print(json_output)
Using the default
parameter in json.dumps()
for datetime
serialization.