You can add the 'default' parameter to json.dumps to handle this:
date_handler = lambda obj: (
obj.isoformat()
if isinstance(obj, (datetime.datetime, datetime.date))
else None
)
json.dumps(datetime.datetime.now(), default=date_handler)
'"2010-04-20T20:08:21.634121"'
Which is ISO 8601 format.
A more comprehensive default handler function:
def handler(obj):
if hasattr(obj, 'isoformat'):
return obj.isoformat()
elif isinstance(obj, ...):
return ...
else:
raise TypeError, 'Object of type %s with value of %s is not JSON serializable' % (type(obj), repr(obj))
Update: Added output of type as well as value.
Update: Also handle date
For cross-language projects, I found out that strings containing RfC 3339 dates are the best way to go. An RfC 3339 date looks like this:
1985-04-12T23:20:50.52Z
I think most of the format is obvious. The only somewhat unusual thing may be the "Z" at the end. It stands for GMT/UTC. You could also add a timezone offset like +02:00 for CEST (Germany in summer). I personally prefer to keep everything in UTC until it is displayed.
For displaying, comparisons and storage you can leave it in string format across all languages. If you need the date for calculations easy to convert it back to a native date object in most language.
So generate the JSON like this:
json.dump(datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ'))
Unfortunately, Javascript's Date constructor doesn't accept RfC 3339 strings but there are many parsers available on the Internet.
huTools.hujson tries to handle the most common encoding issues you might come across in Python code including date/datetime objects while handling timezones correctly.
I've worked it out.
Let's say you have a Python datetime object, d, created with datetime.now(). Its value is:
datetime.datetime(2011, 5, 25, 13, 34, 5, 787000)
You can serialize it to JSON as an ISO 8601 datetime string:
import json
json.dumps(d.isoformat())
The example datetime object would be serialized as:
'"2011-05-25T13:34:05.787000"'
This value, once received in the Javascript layer, can construct a Date object:
var d = new Date("2011-05-25T13:34:05.787000");
As of Javascript 1.8.5, Date objects have a toJSON method, which returns a string in a standard format. To serialize the above Javascript object back to JSON, therefore, the command would be:
d.toJSON()
Which would give you:
'2011-05-25T20:34:05.787Z'
This string, once received in Python, could be deserialized back to a datetime object:
datetime.strptime('2011-05-25T20:34:05.787Z', '%Y-%m-%dT%H:%M:%S.%fZ')
This results in the following datetime object, which is the same one you started with and therefore correct:
datetime.datetime(2011, 5, 25, 20, 34, 5, 787000)
Using json
, you can subclass JSONEncoder and override the default() method to provide your own custom serializers:
import json
import datetime
class DateTimeJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return obj.isoformat()
else:
return super(DateTimeJSONEncoder, self).default(obj)
Then, you can call it like this:
>>> DateTimeJSONEncoder().encode([datetime.datetime.now()])
'["2010-06-15T14:42:28"]'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With