我有一个基本的字典如下:

sample = {}
sample['title'] = "String"
sample['somedate'] = somedatetimehere

当我尝试做jsonify(sample)时,我得到:

TypeError: datetime.datetime(2012, 8, 8, 21, 46, 24, 862000) is not JSON serializable

我该怎么做才能使我的字典样本克服上面的错误呢?

注意:虽然它可能不相关,字典是从mongodb的记录检索中生成的,当我打印出str(sample['somedate'])时,输出是2012-08-08 21:46:24.862000。


当前回答

如果在视图中使用结果,请确保返回正确的响应。根据API, jsonify执行以下操作:

使用给定参数的JSON表示创建一个Response 用一个application/json mimetype。

使用json模拟此行为。转储您必须添加几行额外的代码。

response = make_response(dumps(sample, cls=CustomEncoder))
response.headers['Content-Type'] = 'application/json'
response.headers['mimetype'] = 'application/json'
return response

您还应该返回一个dict以完全复制jsonify的响应。整个文件是这样的

from flask import make_response
from json import JSONEncoder, dumps


class CustomEncoder(JSONEncoder):
    def default(self, obj):
        if set(['quantize', 'year']).intersection(dir(obj)):
            return str(obj)
        elif hasattr(obj, 'next'):
            return list(obj)
        return JSONEncoder.default(self, obj)

@app.route('/get_reps/', methods=['GET'])
def get_reps():
    sample = ['some text', <datetime object>, 123]
    response = make_response(dumps({'result': sample}, cls=CustomEncoder))
    response.headers['Content-Type'] = 'application/json'
    response.headers['mimetype'] = 'application/json'
    return response

其他回答

我在外部化django模型对象转储为JSON时也遇到了同样的问题。 以下是解决方法。

def externalize(model_obj):
  keys = model_obj._meta.get_all_field_names() 
  data = {}
  for key in keys:
    if key == 'date_time':
      date_time_obj = getattr(model_obj, key)
      data[key] = date_time_obj.strftime("%A %d. %B %Y")
    else:
      data[key] = getattr(model_obj, key)
  return data

试着用一个例子来解析它:

#!/usr/bin/env python

import datetime
import json

import dateutil.parser  # pip install python-dateutil


class JSONEncoder(json.JSONEncoder):

    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.isoformat()
        return super(JSONEncoder, self).default(obj)


def test():
    dts = [
        datetime.datetime.now(),
        datetime.datetime.now(datetime.timezone(-datetime.timedelta(hours=4))),
        datetime.datetime.utcnow(),
        datetime.datetime.now(datetime.timezone.utc),
    ]
    for dt in dts:
        dt_isoformat = json.loads(json.dumps(dt, cls=JSONEncoder))
        dt_parsed = dateutil.parser.parse(dt_isoformat)
        assert dt == dt_parsed
        print(f'{dt}, {dt_isoformat}, {dt_parsed}')
        # 2018-07-22 02:22:42.910637, 2018-07-22T02:22:42.910637, 2018-07-22 02:22:42.910637
        # 2018-07-22 02:22:42.910643-04:00, 2018-07-22T02:22:42.910643-04:00, 2018-07-22 02:22:42.910643-04:00
        # 2018-07-22 06:22:42.910645, 2018-07-22T06:22:42.910645, 2018-07-22 06:22:42.910645
        # 2018-07-22 06:22:42.910646+00:00, 2018-07-22T06:22:42.910646+00:00, 2018-07-22 06:22:42.910646+00:00


if __name__ == '__main__':
    test()

在其他答案的基础上,一个简单的解决方案基于只转换datetime的特定序列化器。Datetime和Datetime。将对象日期指定为字符串。

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.

这个json_serial函数可以这样使用:

from datetime import datetime
from json import dumps

print dumps(datetime.now(), default=json_serial)

详细说明如何将默认参数设置为json。可以在json模块文档的基本用法章节中找到dump作品。

我可能不是百分百正确, 这是实现序列化的简单方法

#!/usr/bin/python
import datetime,json

sampledict = {}
sampledict['a'] = "some string"
sampledict['b'] = datetime.datetime.now()

print sampledict   # output : {'a': 'some string', 'b': datetime.datetime(2017, 4, 15, 5, 15, 34, 652996)}

#print json.dumps(sampledict)

'''
output : 

Traceback (most recent call last):
  File "./jsonencodedecode.py", line 10, in <module>
    print json.dumps(sampledict)
  File "/usr/lib/python2.7/json/__init__.py", line 244, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python2.7/json/encoder.py", line 184, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: datetime.datetime(2017, 4, 15, 5, 16, 17, 435706) is not JSON serializable


'''

sampledict['b'] = datetime.datetime.now().strftime("%B %d, %Y %H:%M %p")

afterdump = json.dumps(sampledict)

print afterdump  #output : {"a": "some string", "b": "April 15, 2017 05:18 AM"}

print type(afterdump) #<type 'str'>


afterloads = json.loads(afterdump) 

print afterloads # output : {u'a': u'some string', u'b': u'April 15, 2017 05:18 AM'}


print type(afterloads) # output :<type 'dict'> 

如果你在通信的双方,你可以使用repr()和eval()函数和json。

import datetime, json

dt = datetime.datetime.now()
print("This is now: {}".format(dt))

dt1 = json.dumps(repr(dt))
print("This is serialised: {}".format(dt1))

dt2 = json.loads(dt1)
print("This is loaded back from json: {}".format(dt2))

dt3 = eval(dt2)
print("This is the same object as we started: {}".format(dt3))

print("Check if they are equal: {}".format(dt == dt3))

您不应该导入datetime as

from datetime import datetime

因为eval会报错。或者您可以将datetime作为参数传递给eval。在任何情况下,这都是可行的。