Why does json serialization of datetime objects in python not work out of the box for datetime objects

PythonJsonSerializationSimplejson

Python Problem Overview


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?

Python Solutions


Solution 1 - Python

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 - Python

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 - Python

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 - Python

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondusualView Question on Stackoverflow
Solution 1 - PythonVikasView Answer on Stackoverflow
Solution 2 - PythonMartijn PietersView Answer on Stackoverflow
Solution 3 - PythondavidhadasView Answer on Stackoverflow
Solution 4 - PythonMarkView Answer on Stackoverflow