Why does json serialization of datetime objects in python not work out of the box for datetime objects
Why does the json serialization not work for datetime objects . As I understand json serialization the basic idea for any object can be call the __str__
builtin function and then urlencode the object that you get as a response. But in case of datetime i get the following error
TypeError: datetime.datetime(2012, 5, 23, 18, 38, 23, 37566) is not JSON serializable
while there is a __str__
i.e a way of stringifying the object already available , But it seems like a conscious decision to not do it , why would that be the case?
Solution 1:
No it doesn't work that way in json
module. The module provides you with a default encoder: json.JSONEncoder
. You need to extend this to provide your implementation of default
method to serialize objects. Something like this:
import json
import datetime
from time import mktime
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return int(mktime(obj.timetuple()))
return json.JSONEncoder.default(self, obj)
print json.dumps(obj, cls=MyEncoder)
As others correctly pointed out, the reason is that the standard for json does not specify how date time can be represented.
Solution 2:
How would you like them to be serialized?
JSON doesn't specify how to handle dates, so the python json
library cannot make the decision on how to then represent these for you. That completely depends on how the other side (browser, script, whatever) handles dates in JSON as well.
Solution 3:
A simple way to patch the json module such that serialization would support datetime.
import json
import datetime
json.JSONEncoder.default = lambda self,obj: (obj.isoformat() if isinstance(obj, datetime.datetime) else None)
Than use json serialization as you always do - this time with datetime being serialized as isoformat.
json.dumps({'created':datetime.datetime.now()})
Resulting in: '{"created": "2015-08-26T14:21:31.853855"}'
See more details and some words of caution at: StackOverflow: JSON datetime between Python and JavaScript
Solution 4:
If you want to get encoding and decoding of datetimes without having to implement it, you can use json_tricks, which is a wrapper that adds encoding and decoding for various popular types. Just install:
pip install json_tricks
and then import from json_tricks
instead of json
, e.g.:
from json_tricks import dumps, loads
json = dumps({'name': 'MyName', 'birthday': datetime.datetime(1992, 5, 23, 18, 38, 23, 37566)})
me = loads(json)
Disclaimer: it's made by me. Because I had the same problem.
If you want to automatically serialize anything that can be stringified, you can do that with just the standard implementation very easily:
dumps(obj, default=str)
But note that this has disadvantages, e.g. none of it will be deserialized without extra effort, and maybe sometimes you just don't want to serialize something (like a function of a big numpy array) but get a warning instead, which this method will silence.