Skip to main content

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}")

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 custom default function in json.dumps
  • Using a custom JSONEncoder that checks isinstance(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:

  1. Convert to String First (Recommended for Control): Manually convert the datetime or Timestamp objects to strings using .isoformat() (preferred), str(), or .strftime() before calling json.dumps().
  2. Use default=str or default=custom_func: Let json.dumps() handle the conversion during serialization. Using default=str is simple; a custom function offers more control (e.g., using isoformat).
  3. Use a Custom JSONEncoder: Subclass json.JSONEncoder for reusable or more complex serialization logic.

Representing dates and times as ISO 8601 strings is generally the best practice for JSON serialization.