python - How to overcome "datetime.datetime not JSON serializable"?

ID : 1358

viewed : 128

Tags : pythonjsonpython

Top 5 Answer for python - How to overcome "datetime.datetime not JSON serializable"?

vote vote

94

My quick & dirty JSON dump that eats dates and everything:

json.dumps(my_dictionary, indent=4, sort_keys=True, default=str) 

default is a function applied to objects that aren't serializable.
In this case it's str, so it just converts everything it doesn't know to strings. Which is great for serialization but not so great when deserializing (hence the "quick & dirty") as anything might have been string-ified without warning, e.g. a function or numpy array.

vote vote

80

Building on other answers, a simple solution based on a specific serializer that just converts datetime.datetime and datetime.date objects to strings.

from datetime import date, datetime  def json_serial(obj):     """JSON serializer for objects not serializable by default json code"""      if isinstance(obj, (datetime, date)):         return obj.isoformat()     raise TypeError ("Type %s not serializable" % type(obj)) 

As seen, the code just checks to find out if object is of class datetime.datetime or datetime.date, and then uses .isoformat() to produce a serialized version of it, according to ISO 8601 format, YYYY-MM-DDTHH:MM:SS (which is easily decoded by JavaScript). If more complex serialized representations are sought, other code could be used instead of str() (see other answers to this question for examples). The code ends by raising an exception, to deal with the case it is called with a non-serializable type.

This json_serial function can be used as follows:

from datetime import datetime from json import dumps  print dumps(datetime.now(), default=json_serial) 

The details about how the default parameter to json.dumps works can be found in Section Basic Usage of the json module documentation.

vote vote

71

Updated for 2018

The original answer accommodated the way MongoDB "date" fields were represented as:

{"$date": 1506816000000}

If you want a generic Python solution for serializing datetime to json, check out @jjmontes' answer for a quick solution which requires no dependencies.


As you are using mongoengine (per comments) and pymongo is a dependency, pymongo has built-in utilities to help with json serialization:
http://api.mongodb.org/python/1.10.1/api/bson/json_util.html

Example usage (serialization):

from bson import json_util import json  json.dumps(anObject, default=json_util.default) 

Example usage (deserialization):

json.loads(aJsonString, object_hook=json_util.object_hook) 

Django

Django provides a native DjangoJSONEncoder serializer that deals with this kind of properly.

See https://docs.djangoproject.com/en/dev/topics/serialization/#djangojsonencoder

from django.core.serializers.json import DjangoJSONEncoder  return json.dumps(   item,   sort_keys=True,   indent=1,   cls=DjangoJSONEncoder ) 

One difference I've noticed between DjangoJSONEncoder and using a custom default like this:

import datetime import json  def default(o):     if isinstance(o, (datetime.date, datetime.datetime)):         return o.isoformat()  return json.dumps(   item,   sort_keys=True,   indent=1,   default=default ) 

Is that Django strips a bit of the data:

 "last_login": "2018-08-03T10:51:42.990", # DjangoJSONEncoder   "last_login": "2018-08-03T10:51:42.990239", # default 

So, you may need to be careful about that in some cases.

vote vote

60

I have just encountered this problem and my solution is to subclass json.JSONEncoder:

from datetime import datetime import json  class DateTimeEncoder(json.JSONEncoder):     def default(self, o):         if isinstance(o, datetime):             return o.isoformat()          return json.JSONEncoder.default(self, o) 

In your call do something like: json.dumps(yourobj, cls=DateTimeEncoder) The .isoformat() I got from one of the answers above.

vote vote

55

Convert the date to a string

sample['somedate'] = str( datetime.utcnow() ) 

Top 3 video Explaining python - How to overcome "datetime.datetime not JSON serializable"?

Related QUESTION?