无法从 Cherrypy 将日期时间序列化为 JSON

发布于 2024-12-13 17:21:35 字数 831 浏览 0 评论 0原文

我正在尝试发送记录列表以响应 Ajax 查询。除非结果包含日期时间字段(当我的进程失败并出现错误 datetime.date(2011, 11, 1) is not JSON可序列化)时,此方法效果很好。

我尝试将我找到的答案与此处的一个非常类似问题结合起来并附有说明在 CherryPy 文档 中使用自定义 json_out 编码器,但是我不清楚该函数必须具有什么签名。我编写的函数是:

 def json_encoder(thing):

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

现在任何使用 json_out (即使输出中没有日期时间)都会给我错误 TypeError: json_encoder() gets正好 1 个参数(0 给定).但是如果编码器不接受参数,它如何接收要编码的对象?

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

I'm attempting to send a list of records in response to an Ajax query. This works well unless the results include a datetime field when my process fails with the error datetime.date(2011, 11, 1) is not JSON serializable.

I attempted to combine the answer I found to a very similar question here with instructions in the CherryPy documentation to use a custom json_out encoder, but it's not clear to me what signature that function must have. The function I wrote is:

 def json_encoder(thing):

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

and now any use of json_out (even with no datetime in the output) gives me the error TypeError: json_encoder() takes exactly 1 argument (0 given). But if the encoder doesn't take an argument, how does it receive the object to encode?

(Also, I assume my use of str(thing) as the default method of encoding is wrong and that this should be done with a call to whatever the default handler for json encoding is, but I'm not sure how to call that method).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我不咬妳我踢妳 2024-12-20 17:21:35

我遇到了同样的问题(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):
         ...

I got the same problem (Python 3.2, Cherrypy 3.2.2) and I solved it with the following code:

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)

And then you can use the Cherrypy json_out decorator:

class Root:
     @cherrypy.expose
     @cherrypy.tools.json_out(handler=json_handler)
     def default(self, *args, **kwargs):
         ...
岛歌少女 2024-12-20 17:21:35

我在类似的情况下执行下一步:

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)

I do the next in a similar case:

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

and at the call:

json.dumps(my_variable, cls=DecimalEncoder)

So in your case it should be like:

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)
番薯 2024-12-20 17:21:35

对于自定义 json_handler 实现,请参阅 Pierre 的优秀答案。但是,每次使用该工具时都指定 @cherrypy.tools.json_out(handler=json_handler) 有点麻烦,因此 jsontools.json_out源码指出,就是更好地使用这个:

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

此外,您可以在课堂上启用工具使用 _cp_config

class Example
_cp_config = {
  'tools.json_out.on': True
}

For custom json_handler implementation, see Pierre's excellent answer. However, specifying @cherrypy.tools.json_out(handler=json_handler) every time you use the tool is a bit cumbersome, so as the jsontools.json_out source code points out, it's better to use this:

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

Also, you can enable tools on class level using _cp_config:

class Example
_cp_config = {
  'tools.json_out.on': True
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文