TypeError: Object of type datetime is not JSON serializable

avatar

Borislav Hadzhiev

Last updated: Apr 20, 2022

banner

Check out my new book

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.

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": "2022-05-22 16:14:39.331207"}'' print(type(json_str)) # 👉️ <class 'str'>

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.

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": "2022-05-22 16:21:25.460716"}' 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 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 classes' 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 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() # ✅ pass cls keyword argument json_str = json.dumps({'created_at': now}, cls=DTEncoder) print(json_str) # 👉️ '{"created_at": "2022-05-22 16:21:25.460716"}' print(type(json_str)) # 👉️ <class 'str'>

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

Use the search field on my Home Page to filter through my more than 3,000 articles.