【问题标题】:Python Flask-Restful POST not taking JSON argumentsPython Flask-Restful POST 不采用 JSON 参数
【发布时间】:2015-08-10 02:13:17
【问题描述】:

我对 Flask(和 Flask-Restful)非常陌生。

我的问题:POSTjson 参数设置为 NONE(不起作用)。

我可以使用 POSTMAN chrome 插件从 form-data 获取参数。但是,当我切换到raw(并提供json)时,它无法读取json并为我的所有参数分配NONE

我已经阅读了一些与此相关的 stackoverflow 帖子:link1link2link3 ...这些都没有帮助我。

我在 Oracle Linux 6.5 上使用 python-2.6Flask-Restful-0.3.3Flask-0.10.1ChromePOSTMAN

Python 代码 app.py :

from flask import Flask, jsonify
from flask_restful import reqparse, abort, Api, Resource

app = Flask(__name__)
api = Api(app)

parser = reqparse.RequestParser()
parser.add_argument('username', type=str)
parser.add_argument('password', type=str)

class HelloWorld(Resource):
    def post(self):
        args = parser.parse_args()
        un = str(args['username'])
        pw = str(args['password'])
        return jsonify(u=un, p=pw)

api.add_resource(HelloWorld, '/testing')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5444 ,debug=True)

测试这个使用POSTMAN

  • 使用form-data:完美运行!
  • 使用 raw -> json : 导致此问题

尝试#1

app.py 中将json 参数添加到我的add_argument() 方法中

parser = reqparse.RequestParser()
parser.add_argument('username', type=str, location='json') # added json
parser.add_argument('password', type=str, location='json') # added json

Input : { "username": "hello", "password": "world" }

Output:{“p”:“无”,“u”:“无”}

尝试#2

app.py中的add_argument()方法中将类型更改为unicode

parser = reqparse.RequestParser()
parser.add_argument('username', type=unicode, location='json') # change type to unicode
parser.add_argument('password', type=unicode, location='json') # change type to unicode

Input : { "username": "hello", "password": "world" }

Output:{“p”:“无”,“u”:“无”}


PS: 我会不断更新我的问题,每次失败的尝试。 如果您需要更多信息以使这个问题更清楚,请告诉我。

【问题讨论】:

  • 在我看来,您好像错过了对 parser.parse_args() 的呼叫。您应该先拥有args = parser.parse_args(),然后才能访问args
  • @junnytony - 这是我这边的错字,我忘了复制那行。立即编辑问题!
  • 对参数类型尝试unicode 而不是str
  • @Sir_FZ unicode 有同样的问题,保留None

标签: python json rest flask flask-restful


【解决方案1】:

在强制请求解析 json 之后,它对我有用。 代码如下:

from flask import Flask, jsonify, request
from flask_restful import reqparse, abort, Api, Resource

app = Flask(__name__)
api = Api(app)

parser = reqparse.RequestParser()
parser.add_argument('username', type=str)
parser.add_argument('password', type=str)

class HelloWorld(Resource):
    def post(self):
        request.get_json(force=True)
        args = parser.parse_args()
        un = str(args['username'])
        pw = str(args['password'])
        return jsonify(u=un, p=pw)

api.add_resource(HelloWorld, '/testing')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5444 ,debug=True)

【讨论】:

    【解决方案2】:

    我遇到了类似的问题,这里有一个适合我的解决方案。假设您的应用程序如下所示:

    from flask import Flask, jsonify
    from flask_restful import Api, Resource, reqparse
    
    app = Flask(__name__)
    api = Api(app)
    
    # Define parser and request args
    parser = reqparse.RequestParser()
    parser.add_argument('last_name', type=str)
    parser.add_argument('first_name', type=str)
    # not the type=dict
    parser.add_argument('personal_data', type=dict)
    
    
    class Item(Resource):
    
        def post(self):
    
            args = parser.parse_args()
    
            ln = args['last_name']
            fn = args['first_name']
            # we can also easily parse nested structures
            age = args['personal_data']['age']
            nn = args['personal_data']['nicknames']
    
            return jsonify(fn=fn, ln=ln, age=age, nn=nn)
    
    
    api.add_resource(Item, '/item')
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    现在,您可以轻松创建一些 JSON 数据:

    import json
    
    d = {'last_name': 'smith', 'first_name': 'john', 'personal_data': {'age': 18, 'height': 180, 'nicknames': ['johnny', 'grandmaster']}}
    
    print(json.dumps(d, indent=4))
    
    {
        "last_name": "smith",
        "first_name": "john",
        "personal_data": {
            "age": 18,
            "height": 180,
            "nicknames": [
                "johnny",
                "grandmaster"
            ]
        }
    }
    
    json.dumps(d)
    '{"last_name": "smith", "first_name": "john", "personal_data": {"age": 18, "height": 180, "nicknames": ["johnny", "grandmaster"]}}'
    

    并调用应用程序:

    curl http://localhost:5000/item -d '{"last_name": "smith", "first_name": "john", "personal_data": {"age": 18, "height": 180, "nicknames": ["johnny", "grandmaster"]}}'
    

    这将因错误而崩溃(我缩短了回溯):

    年龄 = args['personal_data']['age']
    TypeError: 'NoneType' 对象不可下标

    原因是没有指定标头。如果我们添加

    -H "Content-Type: application/json"
    

    然后调用

    curl http://localhost:5000/item -H "Content-Type: application/json" -d '{"last_name": "smith", "first_name": "john", "personal_data": {"age": 18, "height": 180, "nicknames": ["johnny", "grandmaster"]}}'
    

    输出看起来如预期:

    {
      "age": 18, 
      "fn": "john", 
      "ln": "smith", 
      "nn": [
        "johnny", 
        "grandmaster"
      ]
    }
    

    函数还可以进一步简化为:

    class Item(Resource):
    
        def post(self):
    
            json_data = request.get_json()
            # create your response below
    

    作为shown above

    【讨论】:

      【解决方案3】:

      根据Request.json 和新Request.get_json 的文档,您应该将POST 请求的mimetype 设置为application/json。这是 Flask 自动将您的 JSON 数据解析为 Request.json 属性的唯一方法,(我相信)这是 Flask-Restful 检索 JSON 数据所依赖的。

      注意:较新的 get_json 函数具有一个选项,可以强制将 POST 数据解析为 JSON,而不管 MIME 类型如何

      【讨论】:

        【解决方案4】:

        junnytony 的回答给了我一个提示,我继续采用这种方法。 get_json 似乎成功了。

        from flask import Flask, jsonify, request
        from flask_restful import reqparse, abort, Api, Resource
        
        app = Flask(__name__)
        api = Api(app)
        
        #parser = reqparse.RequestParser()
        #parser.add_argument('username', type=unicode, location='json')
        #parser.add_argument('password', type=unicode, location='json')
        
        class HelloWorld(Resource):
            def post(self):
                json_data = request.get_json(force=True)
                un = json_data['username']
                pw = json_data['password']
                #args = parser.parse_args()
                #un = str(args['username'])
                #pw = str(args['password'])
                return jsonify(u=un, p=pw)
        
        api.add_resource(HelloWorld, '/testing')
        
        if __name__ == '__main__':
            app.run(host='0.0.0.0', port=5444 ,debug=True)
        

        【讨论】:

        • 很好:)。但我认为如果您将帖子的 mimetype 更改为“application/json”,您的代码会更加出色。我猜你正在为你的帖子使用 AJAX。使用 jQuery 之类的东西,您可以轻松添加适当的 mimetype,例如 stackoverflow.com/questions/6323338/…
        • 感谢您提供最终代码,我有一个类似的用例。
        • 您好,我也面临同样的问题。根据您的建议,我完成了但仍然收到错误的请求错误
        • 你的具体问题是什么@KCN?
        • 根据你的建议,我遵循了 json_dat = request.get_json(force=True) fname = json_dat["firstname"] lname = json_dat["lastname"] 但是在从休息客户端执行这个 url 时400 错误请求错误
        猜你喜欢
        • 2013-11-23
        • 2019-05-04
        • 2018-12-02
        • 2021-03-26
        • 2017-02-24
        • 2015-02-20
        • 1970-01-01
        • 2014-07-21
        • 1970-01-01
        相关资源
        最近更新 更多