is there any elegant way to make Python JSON encoder support datetime? some 3rd party module or easy hack?
I am using tornado's database wrapper to fetch some rows from db to generate a json. The query result includes a regular MySQL timestamp column.
It's quite annoying that Python's default json encoder doesn't support its own datetime type, which is so common in all kinds of database queries.
I don't want to modify Python's own json encoder. any good practice? Thanks a lot!
ps: I found a dirty hack by modifying the Python JSON encoder default method:
Change:
def default(self, o):
raise TypeError(repr(o) + " is not JSON serializable")
To:
def default(self, o):
from datetime import date
from datetime import datetime
if isinstance(o, datetime):
return o.isoformat()
elif isinstance(o, date):
return o.isoformat()
else:
raise TypeError(repr(o) + " is not JSON serializable")
well, it will be a temporary solution just for dev environment.
But for long term solution or production environment, this is quite ugly, and I have to do the modification every time I deploy to a new server.
Is there a better way? I do not want to modify Python code itself, neither Tornado source code. Is there something I can do with my own project code to make this happen? preferably in one pace.
Thanks a lot!
The docs suggest subclassing JSONEncoder and implementing your own default method. Seems like you're basically there.
The reason dates aren't handled by the default encoder is there is no standard representation of a date in JSON. Some people are using the format /Date(1198908717056)/
, but I prefer ISO format personally.
import json
import datetime
class DateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, (datetime.datetime, datetime.date, datetime.time)):
return obj.isoformat()
elif isinstance(obj, datetime.timedelta):
return (datetime.datetime.min + obj).time().isoformat()
return super(DateTimeEncoder, self).default(obj)
now = datetime.datetime.now()
encoder = DateTimeEncoder()
encoder.encode({"datetime": now, "date": now.date(), "time": now.time()})
> {"datetime": "2019-07-02T16:17:09.990126", "date": "2019-07-02", "time": "16:17:09.990126"}