【问题标题】:Python Tornado request JSONPython Tornado 请求 JSON
【发布时间】:2020-07-10 05:31:15
【问题描述】:

我的应用程序接受来自我通过 JQuery 的 AJAX 请求运行的 POST 方法的数据。我正在发送 JSON 格式的数据,但是在处理程序中,当我接受请求并访问它原来是字节字符串类型的数据时。

我正在使用my_body = self.request.body 方法。

例如,如果我发送{"drzava":"rs","kategorija":"general"},接收到的数据看起来像b'drzava=rs&kategorija=general'

问题是,之后我不能使用tornado.escape.json_decode() 来使其成为字典。我不断收到以下错误:

Traceback (most recent call last):
  File "/home/stefan/.local/lib/python3.6/site-packages/tornado/web.py", line 1697, in _execute
    result = method(*self.path_args, **self.path_kwargs)
  File "main.py", line 164, in post
    telo_json = tornado.escape.json_decode(telo)
  File "/home/stefan/.local/lib/python3.6/site-packages/tornado/escape.py", line 83, in json_decode
    return json.loads(to_basestring(value))
  File "/usr/lib/python3.6/json/__init__.py", line 354, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.6/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.6/json/decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

如果需要,我会发布代码。

【问题讨论】:

    标签: python json ajax tornado


    【解决方案1】:

    您在 Tornado 服务器应用程序中收到的数据取决于客户端如何“打包”您的数据。

    您可以拥有 application/x-www-form-urlencoded 数据(上面似乎是您的情况),您可以使用 get_body_argument 在 Tornado 中处理这些数据:

    drzava = self.get_body_argument("drzava", None)
    kategorija = self.get_body_argument("kategorija", None)
    

    或者你可以有application/json(似乎是你想要的):

    data = tornado.escape.json_decode(self.request.body)
    

    为了从浏览器发送 JSON 数据,您需要实际发送 JSON 数据并指定内容类型:

    var data = {"drzava":"rs", "kategorija":"general"};
    $.ajax({
        url: YOUR_URL,
        type: "POST",
        data: JSON.stringify(data),
        contentType: "application/json",
        ...
    

    编辑:
    最后的问题是 HTML 页面使用表单发送数据,实际上并没有使用 JS 代码。

    【讨论】:

    • 这正是我发送数据的方式。
    • 您确定您使用的是data: JSON.stringify(data)吗?因为从你上面的问题看来你不是。
    • 是的。这是页面上运行的 .js 脚本:var posiljka = { drzava: $drzava.val(), kategorija: $kategorija.val() }; $ajax({ type: 'POST', url: 'localhost:8000', data: JSON.stringify(posiljka), dataType: "json", success: function(){ alert('poslato'); }, error: function(){ alert('greska'); } });
    • 您使用的是dataType: "json",它用于告诉服务器您期望什么响应contentType 用于指定您发送的内容。
    • 是的。改正了,还是一样的结果。
    【解决方案2】:

    更新: 首先,我的.js 文件中有错字,所以AJAX 请求没有被发送。其次,Tornado 正在检测默认的POST 方法(不是AJAX 的方法),因此您必须通过说类似e.preventDefault(); 的内容手动覆盖它,其中eJQUERY 中匿名函数的参数行动。另一方面,在 Tornado 中,self.request.body 的结果类似于b'{"country":"rs","category":"sports"}'可以使用tornado.escape.json_decode() 转换为字典。非常感谢@Ionut Ticus 的建设性建议。

    所以,经过一番调查和阅读文档,我发现了以下内容:

    HTTPServerRequest.body 现在总是一个字节字符串(以前是 默认的空正文将是 python 3) 上的 aunicode 字符串

    这是 Tornado 的官方文档。 Tornado Documentation Release 6.0.4 page 183

    不过,我找到了解决办法。

    argumenti = self.request.arguments
    drzava_val = argumenti['drzava'][0].decode("utf-8")
    kategorija_val =  argumenti['kategorija'][0].decode("utf-8")
    
    data = {
                'drzava': drzava_val,
                'kategorija': kategorija_val
            }
    

    【讨论】:

    • 如果没有指定任何不理想的参数,上面的代码将引发异常;使用self.get_body_argument(KEY, DEFAULT_VALUE)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 2011-05-20
    • 2013-11-12
    • 2013-06-12
    相关资源
    最近更新 更多