无法将日期时间序列化为来自Cherrypy的JSON

时间:2011-11-04 14:49:25

标签: python json datetime cherrypy

我正在尝试发送一个记录列表以响应Ajax查询。除非结果包含日期时间字段,否则当我的流程因错误datetime.date(2011, 11, 1) is not JSON serializable而失败时,这种情况很有效。

我尝试将我在similar question发现的答案与CherryPy documentation中的说明结合使用自定义json_out编码器,但我不清楚该函数必须具有哪些签名。我写的函数是:

 def json_encoder(thing):

      if hasattr(thing, 'isoformat'):
           return thing.isoformat()
      else:
           return str(thing)

现在任何使用json_out(即使输出中没有日期时间)也会给出错误TypeError: json_encoder() takes exactly 1 argument (0 given)。但是如果编码器没有参数,它如何接收要编码的对象?

(另外,我假设我使用str(thing)作为默认的编码方法是错误的,这应该通过调用json编码的默认处理程序来完成,但我不知道如何称这种方法。)

3 个答案:

答案 0 :(得分:9)

我在类似的情况下做下一个:

class DecimalEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Decimal):
            return float(obj)
        return json.JSONEncoder.default(self, obj)

并致电:

json.dumps(my_variable, cls=DecimalEncoder)

所以在你的情况下它应该是:

class DateEncoder(json.JSONEncoder):
    def default(self, obj):
        if hasattr(obj, 'isoformat'):
            return obj.isoformat()
        else:
            return str(obj)
        return json.JSONEncoder.default(self, obj)


json.dumps(my_variable, cls=DateEncoder)

答案 1 :(得分:9)

我遇到了同样的问题(Python 3.2,Cherrypy 3.2.2),我用以下代码解决了这个问题:

import cherrypy
import json
import datetime
class _JSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.date):
            return obj.isoformat()
        return super().default(obj)
    def iterencode(self, value):
        # Adapted from cherrypy/_cpcompat.py
        for chunk in super().iterencode(value):
            yield chunk.encode("utf-8")

json_encoder = _JSONEncoder()

def json_handler(*args, **kwargs):
    # Adapted from cherrypy/lib/jsontools.py
    value = cherrypy.serving.request._json_inner_handler(*args, **kwargs)
    return json_encoder.iterencode(value)

然后你可以使用Cherrypy json_out装饰器:

class Root:
     @cherrypy.expose
     @cherrypy.tools.json_out(handler=json_handler)
     def default(self, *args, **kwargs):
         ...

答案 2 :(得分:1)

对于自定义sudo service redis-server restart实施,请参阅Pierre的优秀答案。但是,每次使用该工具时指定json_handler都有点麻烦,因此jsontools.json_out source code points out最好使用此工具:

@cherrypy.tools.json_out(handler=json_handler)

此外,您可以使用_cp_config级别启用工具:

cherrypy.config['tools.json_out.handler'] = json_handler