TypeError: Object of type datetime is not JSON serializable

avatar
Borislav Hadzhiev

Last updated: Apr 8, 2024
6 min

banner

# Table of Contents

  1. TypeError: Object of type datetime is not JSON serializable
  2. TypeError: Object of type Timestamp is not JSON serializable

# TypeError: Object of type datetime is not JSON serializable

The Python "TypeError: Object of type datetime is not JSON serializable" occurs when we try to convert a datetime object to a JSON string.

To solve the error, set the default keyword argument to str in your call to the json.dumps() method.

Here is an example of how the error occurs.

main.py
import json from datetime import datetime now = datetime.now() # ⛔️ TypeError: Object of type datetime is not JSON serializable json_str = json.dumps({'created_at': now}, default=str)

We tried passing a datetime object to the json.dumps() method but the method doesn't handle datetime objects by default.

# Supply the default keyword argument to solve the error

To solve the error, pass the default keyword argument setting it to the str class.

main.py
import json from datetime import datetime now = datetime.now() # ✅ set default=str json_str = json.dumps({'created_at': now}, default=str) print(json_str) # 👉️ '{"created_at": "2023-07-19 17:42:13.501631"}' print(type(json_str)) # 👉️ <class 'str'>

supply default keyword argument

The json.dumps method converts a Python object to a JSON formatted string.

The default keyword argument can be set to a function that gets called for objects that can't otherwise be serialized.

We simply convert the datetime object to a string by passing it to the str class.

# Defining a custom JSON serializer function

You can also define a custom JSON serializer function that takes care of converting dates to JSON.

main.py
from datetime import date, datetime import json def json_serializer(obj): if isinstance(obj, (datetime, date)): return obj.isoformat() raise TypeError(f'Type {type(obj)} is not serializable') now = datetime.now() json_str = json.dumps({'created_at': now}, default=json_serializer) # 👇️ {"created_at": "2023-07-19T17:43:33.333829"} print(json_str)

define custom json serializer function

Notice that we set the default keyword argument to the json_serializer function and not the str class.

The function checks if the supplied value is a datetime or date object and if the condition is met, it uses the date.toisoformat() method to return a string representing the date and time in ISO 8601 format.

main.py
from datetime import datetime now = datetime.now() # 👇️ 2023-02-09T09:14:19.515138 print(now.isoformat())

If the value that was passed to the function is not a date object, a TypeError is raised.

# Create a custom DTEncoder class to solve the error

An alternative approach is to extend from the JSONEncoder class and do the conversion only for datetime objects.

main.py
import json from datetime import datetime class DTEncoder(json.JSONEncoder): def default(self, obj): # 👇️ If passed in object is `datetime` object # convert it to a string if isinstance(obj, datetime): return str(obj) # 👇️ otherwise use the default behavior return json.JSONEncoder.default(self, obj) now = datetime.now() json_str = json.dumps({'created_at': now}, cls=DTEncoder) print(json_str) # 👉️ '{"created_at": "2023-07-19 17:45:53.025469"}' print(type(json_str)) # 👉️ <class 'str'>

create custom dtencoder class

We extended from the JSONEncoder class.

The JSONEncoder class supports the following objects and types by default.

PythonJSON
dictobject
list, tuplearray
strstring
int, float, int and float derived Enumsnumber
Truetrue
Falsefalse
Nonenull

Notice that the JSONEncoder class doesn't support datetime object to JSON conversion by default.

We can handle this by extending from the class and implementing a default() method that returns a serializable object.

main.py
import json from datetime import datetime class DTEncoder(json.JSONEncoder): def default(self, obj): # 👇️ If passed in object is datetime object # convert it to a string if isinstance(obj, datetime): return str(obj) # 👇️ otherwise use the default behavior return json.JSONEncoder.default(self, obj)
In our if statement, we check if the passed-in object is an instance of the datetime class and if it is, we convert it to a string and return the result.

In all other cases, we let the base class's default method do the serialization.

To use a custom JSONEncoder, specify it with the cls keyword argument in your call to the json.dumps() method.

main.py
# ✅ pass cls keyword argument json_str = json.dumps({'created_at': now}, cls=DTEncoder)

If you don't provide the cls kwarg, the default JSONEncoder is used.

# Using the strftime() method to solve the error

You can also use the strftime method to convert a datetime object to a string before converting it to JSON.

main.py
import datetime import json now = datetime.datetime.now() a_str = now.strftime('%Y-%m-%d %H:%M:%S') print(a_str) # 👉️ 2023-07-19 17:47:16 json_str = json.dumps(a_str) print(json_str) # 👉️ "2023-07-19 17:47:16"

using strftime method to solve the error

The datetime class has a strftime() method which we can use to get a string representation of the date and time, controlled by an explicit format string.

The code sample formats the datetime object as YYYY-MM-DD HH:MM:SS.

You can also include the milliseconds in the result.

main.py
import datetime import json now = datetime.datetime.now() a_str = now.strftime('%Y-%m-%d %H:%M:%S.%f') print(a_str) # 👉️ 2023-02-09 09:21:44.753545 json_str = json.dumps(a_str) print(json_str) # 👉️ "2023-02-09 09:21:44.753545"

If you want to format the datetime string in a different way, use this table of the docs to look up the format codes you should pass as the second argument to the strftime() method.

# Using the str() class when converting

You can also use the str() class when converting the value to JSON.

main.py
import json from datetime import datetime now = datetime.utcnow() json_str = json.dumps({'created_at': str(now)}) # 👇️ {"created_at": "2023-07-19 14:48:53.801604"} print(json_str)

using str when converting

Instead of relying on the default keyword argument, we explicitly convert the date to a string using the str() class.

# TypeError: Object of type Timestamp is not JSON serializable

The Python "TypeError: Object of type Timestamp is not JSON serializable" occurs when we try to convert a Timestamp object to a JSON string.

To solve the error, convert the Timestamp object to str before serializing it to JSON.

Here is an example of how the error occurs.

main.py
import json import pandas as pd tstamp = pd.Timestamp('2023-01-01T12') # ⛔️ TypeError: Object of type Timestamp is not JSON serializable json_str = json.dumps({'created_at': tstamp})

We tried passing a Timestamp object to the json.dumps() method but the method doesn't handle Timestamp objects by default

# Convert the Timestamp to a str to solve the error

To solve the error, use the built-in str() class to convert the Timestamp to str before serializing it.

main.py
import json import pandas as pd tstamp = pd.Timestamp('2023-01-01T12') # ✅ convert to str json_str = json.dumps({'created_at': str(tstamp)}) print(json_str) # 👉️ '{"created_at": "2023-01-01 12:00:00"} print(type(json_str)) # 👉️ <class 'str'>

The default JSON encoder handles str values, so we can use a native Python str instead of a Timestamp when serializing to JSON.

The json.dumps() method converts a Python object to a JSON formatted string.

# Create a custom PdEncoder class to solve the error

Alternatively, you can extend from the JSONEncoder class and handle the conversions in a default method.

main.py
import json import pandas as pd class PdEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, pd.Timestamp): return str(obj) return json.JSONEncoder.default(self, obj) tstamp = pd.Timestamp('2023-01-01T12') json_str = json.dumps({'created_at': tstamp}, cls=PdEncoder) print(json_str) # 👉️ '{"created_at": "2023-01-01 12:00:00"} print(type(json_str)) # 👉️ <class 'str'>

We extended from the JSONEncoder class.

The JSONEncoder class supports the following objects and types by default.

PythonJSON
dictobject
list, tuplearray
strstring
int, float, int and float derived Enumsnumber
Truetrue
Falsefalse
Nonenull

Notice that the JSONEncoder class doesn't support Timestamp to JSON conversion by default.

We can handle this by extending from the class and implementing a default() method that returns a serializable object.

main.py
import json import pandas as pd class PdEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, pd.Timestamp): return str(obj) return json.JSONEncoder.default(self, obj)

If the passed-in value is a Timestamp, we convert it to a str and return the result.

The isinstance function returns True if the passed-in object is an instance or a subclass of the passed-in class.

In all other cases, we let the base class's default method do the serialization.

To use a custom JSONEncoder, specify it with the cls keyword argument in your call to the json.dumps() method.

main.py
import json import pandas as pd class PdEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, pd.Timestamp): return str(obj) return json.JSONEncoder.default(self, obj) tstamp = pd.Timestamp('2023-01-01T12') json_str = json.dumps({'created_at': tstamp}, cls=PdEncoder) print(json_str) # 👉️ '{"created_at": "2023-01-01 12:00:00"} print(type(json_str)) # 👉️ <class 'str'>

If you don't provide the cls kwarg, the default JSONEncoder is used.

I've also written an article on how to check if a variable is a Datetime object.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.