【问题标题】:Python 3 Tornado bytes and JSON issuesPython 3 Tornado 字节和 JSON 问题
【发布时间】:2015-07-04 00:02:43
【问题描述】:

我偶然发现了 python 3,特别是 tornado 框架。

我的任务是集成 facebook 身份验证,我从这里使用了测试用例:

https://github.com/tornadoweb/tornado/tree/master/demos/facebook

所以重点是user 是一个包含字节数据的字典。

class AuthLoginHandler(BaseHandler, tornado.auth.FacebookGraphMixin):
@tornado.web.asynchronous
    def get(self):
        ....

    def _on_auth(self, user):
        if not user:
            raise tornado.web.HTTPError(500, "Facebook auth failed")
        self.set_secure_cookie("fbdemo_user", tornado.escape.json_encode(user))
        self.redirect(self.get_argument("next", "/"))

_on_auth 总是产生这个错误:b'token or sesion_expire data here' is not JSON serializable

我在 stackoverflow 上发现了几个孤子:

Fix编码前的数据

import collections.abc

def convert(data):
    '''
    Converts bytes data into unicode strings, so this can be encoded into JSON
    '''
    if isinstance(data, str):
        return str(data)
    elif isinstance(data, bytes):
        return data.decode('utf-8')
    elif isinstance(data, collections.abc.Mapping):
        return dict(map(convert, data.items()))
    elif isinstance(data, collections.abc.Iterable):
        return type(data)(map(convert, data))
    else:
        return data
# ... and somewhere in the code
tornado.escape.json_encode(convert(user))

接下来就是扩展json本身了:

import json

class JSONEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, bytes):
            return o.decode('utf-8')
        return json.JSONEncoder.default(self, o)

现在的问题是:为什么像type(data) == <class 'bytes'> 这样的数据会有这样的问题,我做得对吗?

谢谢

【问题讨论】:

  • 问题是 user 不是字典,它是字节字符串 b'token or sesion_expire data here' 确实不是 JSON 可序列化的。我建议在调试器中运行您的代码以找出它来自哪里。

标签: json facebook python-3.x tornado


【解决方案1】:

迟到总比没有好。

Python 3 json 编码器不接受字节字符串。 Tornado 提供了一个方法to_basestring 可以用来解决这个问题。

source doc 对此问题的看法如下:

在python2中,字节和unicode字符串大多是可以互换的,所以 处理用户提供的参数的函数 ascii 字符串常量可以使用其中任何一个,并且应该返回类型 用户提供。在python3中,这两种类型是不可互换的,所以 字节串转unicode需要这个方法。

用法:

tornado.escape.to_basestring(value)

【讨论】:

  • 但我仍然必须遍历每个可能包含字节字符串的键和值。没有函数可以处理带有字节字符串的dict`s到json?扩展 JSONEncoder 是我目前拥有的最简洁的解决方案。
猜你喜欢
  • 2020-06-10
  • 1970-01-01
  • 2020-07-10
  • 1970-01-01
  • 2016-02-21
  • 1970-01-01
  • 1970-01-01
  • 2010-12-16
  • 2017-11-22
相关资源
最近更新 更多