Last updated: Apr 8, 2024
Reading time·6 min
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.
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.
default
keyword argument to solve the errorTo solve the error, pass the default
keyword argument setting it to the str
class.
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'>
The json.dumps method converts a Python object to a JSON formatted string.
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.
You can also define a custom JSON serializer function that takes care of converting dates to JSON.
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)
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.
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.
DTEncoder
class to solve the errorAn alternative approach is to extend from the JSONEncoder
class and do the
conversion only for datetime
objects.
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'>
We extended from the JSONEncoder class.
The JSONEncoder
class supports the following objects and types by default.
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float, int and float derived Enums | number |
True | true |
False | false |
None | null |
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.
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)
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.
# ✅ 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.
strftime()
method to solve the errorYou can also use the strftime
method to convert a datetime
object to a
string before converting it to JSON.
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"
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.
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.
str()
class when convertingYou can also use the str() class when converting the value to JSON.
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)
Instead of relying on the default
keyword argument, we explicitly convert the
date to a string using the str()
class.
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.
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
Timestamp
to a str
to solve the errorTo solve the error, use the built-in str()
class to convert the Timestamp
to
str
before serializing it.
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.
PdEncoder
class to solve the errorAlternatively, you can extend from the JSONEncoder
class and handle the
conversions in a default
method.
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.
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float, int and float derived Enums | number |
True | true |
False | false |
None | null |
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.
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.
To use a custom JSONEncoder
, specify it with the cls
keyword argument in
your call to the json.dumps()
method.
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.
You can learn more about the related topics by checking out the following tutorials: