背景
在python中,我们使用json.dumps或者tornado的self.write等有关json序列化时,会遇到这些错误:
- TypeError: Decimal('10') is not JSON serializable
- TypeError: datetime.datetime(2019, 8, 22, 19, 37, 48, 481873) is not JSON serializable
解决办法:
import json
from decimal import Decimal
from datetime import datetime,date
class DateEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, datetime):
return o.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(o, date):
return o.strftime("%Y-%m-%d")
elif isinstance(o, Decimal):
return float(o)
else:
return json.JSONEncoder.default(self, o)
d = {"a":Decimal(10),"time":datetime.now(),"c":4}
str_ = json.dumps(d, cls=DateEncoder)
print(str_)
tornado中经常也会碰到这种问题,解决办法当然是重载write方法了,如下:
class DateEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, datetime.datetime):
return o.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(o, datetime.date):
return o.strftime("%Y-%m-%d")
elif isinstance(o, Decimal):
return float(o)
else:
return json.JSONEncoder.default(self, o)
class TestHandler(RequestHandler):
def write(self, chunk):
if self._finished:
raise RuntimeError("Cannot write() after finish()")
if not isinstance(chunk, (bytes, unicode_type, dict)):
message = "write() only accepts bytes, unicode, and dict objects"
if isinstance(chunk, list):
message += ". Lists not accepted for security reasons; see " + \
"http://www.tornadoweb.org/en/stable/web.html#tornado.web.RequestHandler.write"
raise TypeError(message)
if isinstance(chunk, dict):
# 返回数据库数据中存在datetime、date,decimal格式,原write会报错
chunk = json.dumps(chunk, cls=DateEncoder).replace("</", "<\\/")
self.set_header("Content-Type", "application/json; charset=UTF-8")
chunk = escape.utf8(chunk)
self._write_buffer.append(chunk)
网友评论