How to Resolve Python "TypeError: Object of type datetime/Timestamp is not JSON serializable"
When serializing Python objects containing date and time information into JSON format using json.dumps()
, you might encounter errors like TypeError: Object of type datetime is not JSON serializable
or TypeError: Object of type Timestamp is not JSON serializable
. This happens because the standard JSON format doesn't have a native datetime type, and Python's default json
encoder doesn't automatically convert Python's datetime.datetime
or Pandas' Timestamp
objects into a standard JSON representation (like a string).
This guide explains why this error occurs and details several effective methods to serialize these date/time objects into JSON.
Understanding the Error: JSON's Limited Types
JSON has a well-defined set of data types: strings, numbers, booleans (true
/false
), null
, objects ({}
), and arrays ([]
). It does not have a specific type for dates or timestamps. Therefore, when converting Python objects to JSON, date/time objects must be represented using one of the allowed JSON types, most commonly as strings in a standardized format (like ISO 8601) or sometimes as numbers (like Unix timestamps). Python's default json.dumps()
function doesn't automatically perform this conversion for datetime
or Timestamp
objects.
The Cause: json.dumps()
Doesn't Recognize datetime
or Timestamp
The TypeError
is raised because json.dumps()
encounters an object of type datetime.datetime
(or pandas.Timestamp
) within the data structure you're trying to serialize and doesn't have a built-in rule to convert it to a JSON-compatible type.
import json
from datetime import datetime
import pandas as pd # Requires pandas installation
# Example with datetime
now_dt = datetime.now()
data_dt = {'event_time': now_dt, 'event_type': 'LOGIN'}
print(f"Data with datetime: {data_dt}")
try:
# ⛔️ TypeError: Object of type datetime is not JSON serializable
json_output_dt = json.dumps(data_dt)
print(json_output_dt)
except TypeError as e:
print(f"Error (datetime): {e}")
# Example with pandas Timestamp
now_ts = pd.Timestamp.now()
data_ts = {'update_time': now_ts, 'status': 'COMPLETE'}
print(f"Data with timestamp: {data_ts}")
try:
# ⛔️ TypeError: Object of type Timestamp is not JSON serializable
json_output_ts = json.dumps(data_ts)
print(json_output_ts)
except TypeError as e:
print(f"Error (Timestamp): {e}")
Solution 1: Convert to String Before Serialization (Recommended)
The most common and generally recommended approach is to explicitly convert the datetime
or Timestamp
object into a string before passing the data structure to json.dumps()
. This gives you full control over the format.
Using str()
Directly converting using str()
produces a default string format, which is usually acceptable but might not be the standard ISO format.
import json
from datetime import datetime
now_dt = datetime.now()
# ✅ Convert datetime to string using str() before dumps
data_dt_str = {'event_time': str(now_dt), 'event_type': 'LOGIN'}
json_output = json.dumps(data_dt_str)
print(f"Serialized (using str()): {json_output}")
# Output: Serialized (using str()): {"event_time": "2025-04-15 09:29:11.110328", "event_type": "LOGIN"}
Using .isoformat()
(Standard Format)
The .isoformat()
method returns the date/time in the standard ISO 8601 format (e.g., YYYY-MM-DDTHH:MM:SS.ffffff
), which is widely recognized and often preferred for APIs.
import json
from datetime import datetime
now_dt = datetime.now()
# ✅ Convert datetime to string using .isoformat() before dumps
data_dt_iso = {'event_time': now_dt.isoformat(), 'event_type': 'LOGIN'}
json_output = json.dumps(data_dt_iso)
print(f"Serialized (using isoformat()): {json_output}")
# Output: Serialized (using isoformat()): {"event_time": "2025-04-15T09:28:58.675165", "event_type": "LOGIN"}
Using .strftime()
(Custom Format)
If you need a specific custom format, use .strftime()
with the appropriate format codes.
import json
from datetime import datetime
now_dt = datetime.now()
# ✅ Convert datetime to custom string format using .strftime()
custom_format = '%Y/%m/%d %I:%M %p' # e.g., YYYY/MM/DD HH:MM AM/PM
data_dt_custom = {'event_time': now_dt.strftime(custom_format), 'event_type': 'LOGIN'}
json_output = json.dumps(data_dt_custom)
print(f"Serialized (using strftime('{custom_format}')): {json_output}")
# Output: Serialized (using strftime('%Y/%m/%d %I:%M %p')): {"event_time": "2025/04/15 09:28 AM", "event_type": "LOGIN"}
Solution 2: Use the default
Argument in json.dumps()
Instead of converting beforehand, you can tell json.dumps()
how to handle types it doesn't recognize using the default
argument.
Using default=str
This is a simple way to convert any unrecognized object (including datetime
and Timestamp
) to its default string representation during serialization.
import json
from datetime import datetime
import pandas as pd
now_dt = datetime.now()
now_ts = pd.Timestamp.now()
data_mixed = {'dt': now_dt, 'ts': now_ts, 'id': 1}
# ✅ Pass default=str to handle datetime, Timestamp, and potentially others
json_output = json.dumps(data_mixed, default=str)
print(f"Serialized (using default=str): {json_output}")
# Output: Serialized (using default=str): {"dt": "2025-04-15 09:28:14.794045", "ts": "2025-04-15 09:28:14.794054", "id": 1}
This is concise but applies str()
broadly.
Using a Custom default
Function (e.g., with isoformat
)
Provide a custom function that checks the object's type and returns the desired string format (like ISO format), or raises a TypeError
for other unsupported types.
import json
from datetime import date, datetime
import pandas as pd
def datetime_serializer(obj):
"""JSON serializer for datetime/date/Timestamp objects using isoformat."""
if isinstance(obj, (datetime, date, pd.Timestamp)):
return obj.isoformat()
raise TypeError(f"Type {type(obj)} not serializable")
now_dt = datetime.now()
today_d = date.today()
now_ts = pd.Timestamp.now()
data_complex = {'dt': now_dt, 'date': today_d, 'ts': now_ts, 'value': 10}
# ✅ Pass the custom serializer function to default
json_output = json.dumps(data_complex, default=datetime_serializer)
print(f"Serialized (using custom default func): {json_output}")
# Output: Serialized (using custom default func): {"dt": "2025-04-15T09:27:41.088691", "date": "2025-04-15", "ts": "2025-04-15T09:27:41.088724", "value": 10}
This offers more control over formatting and handling different types.
Solution 3: Create a Custom JSONEncoder
Subclass
For reusable or complex serialization logic across your application, subclass json.JSONEncoder
.
import json
from datetime import date, datetime
import pandas as pd
class DateTimeEncoder(json.JSONEncoder):
# Override the default method
def default(self, obj):
if isinstance(obj, (datetime, date, pd.Timestamp)):
return obj.isoformat() # Use ISO format
# Let the base class default method handle other types
# or raise a TypeError
return super(DateTimeEncoder, self).default(obj)
now_dt = datetime.now()
data_to_encode = {'timestamp': now_dt, 'status': 'OK'}
# ✅ Use the custom encoder via the 'cls' argument
json_output = json.dumps(data_to_encode, cls=DateTimeEncoder)
print(f"Serialized (using custom encoder): {json_output}")
# Output: Serialized (using custom encoder): {"timestamp": "2025-04-15T09:27:22.081065", "status": "OK"}
This encapsulates the serialization logic within a class.
Handling Pandas Timestamp
Objects
All the solutions above work for Pandas Timestamp
objects as well:
str(my_timestamp)
my_timestamp.isoformat()
my_timestamp.strftime(...)
- Using
default=str
or a customdefault
function injson.dumps
- Using a custom
JSONEncoder
that checksisinstance(obj, pd.Timestamp)
Choosing the Right String Format
- ISO 8601 (
.isoformat()
): Highly recommended for interoperability. It's a standard, unambiguous format easily parsed by many languages and systems. str()
: Produces a human-readable default format, but less standard for data exchange.strftime()
: Use only when you need a specific, non-standard format required by the receiving system.
Conclusion
The TypeError: Object of type datetime/Timestamp is not JSON serializable
occurs because standard JSON doesn't have dedicated date/time types, and Python's json.dumps
doesn't automatically convert them.
To fix this:
- Convert to String First (Recommended for Control): Manually convert the
datetime
orTimestamp
objects to strings using.isoformat()
(preferred),str()
, or.strftime()
before callingjson.dumps()
. - Use
default=str
ordefault=custom_func
: Letjson.dumps()
handle the conversion during serialization. Usingdefault=str
is simple; a custom function offers more control (e.g., usingisoformat
). - Use a Custom
JSONEncoder
: Subclassjson.JSONEncoder
for reusable or more complex serialization logic.
Representing dates and times as ISO 8601 strings is generally the best practice for JSON serialization.