Why does json serialization of datetime objects in

2019-01-30 17:33发布

问题:

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?

回答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.



回答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.



回答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



回答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.