web-dev-qa-db-ja.com

Python Flask-Restful POST JSON引数を受け取らない

私はFlask(&Flask-Restful)。

私の問題:jsonPOST引数がNONEに設定されています(動作していません)。

ChromeのPOSTMANプラグインを使用して、_form-data_から引数を取ることができます。しかし、私がrawに切り替えると(&feed json)、jsonの読み取りに失敗し、NONEをすべての引数に割り当てます。

私はこれに関連するいくつかの関連するスタックオーバーフローの記事を読みました: link1link2link ...これらのどれも私を助けませんでした。

Oracle Linux 6.5では_python-2.6_、_Flask-Restful-0.3.3_、_Flask-0.10.1_、ChromePOSTMANを使用しています。

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_のadd_argument()メソッドにjsonパラメーターを追加します

_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:試行が失敗するたびに、質問を更新し続けます。この質問をより明確にするためにさらに情報が必要な場合はお知らせください。

22
sudhishkr

Request.json および新しい Request.get_json のドキュメントによると、POSTリクエストはapplication/jsonに設定されているこれが唯一の方法ですflaskは自動的にJSONデータをRequest.jsonプロパティに解析します。これはFlask-RestfulがJSONデータを取得するために依存するものだと思います。

注:新しいget_json関数には、MIMEタイプに関係なく、POSTデータをJSONとして強制的に解析するオプションがあります

20
junnytony

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)
12
sudhishkr

私は同様の問題に遭遇しました、そして、ここに私のために働く解決策があります。アプリケーションが次のように見えるとしましょう:

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"]}}'

これはエラーでクラッシュします(トレースバックを短縮しました):

age = 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

上記 として。

3
Cleb

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)
1
moutaz samir