wake-up-neo.net

Pythonflasche-Restful POST keine JSON-Argumente

Ich bin sehr neu in Flask (& Flask-Restful). 

Mein Problem: json-Argumente für eine POST werden auf NONE gesetzt (funktioniert nicht).

Ich kann Argumente aus dem form-data nehmen, indem ich POSTMAN für Chrome verwendet. Wenn ich jedoch zu raw wechsle (& füttere eine json), kann der Json nicht gelesen werden und weist allen meinen Argumenten eine NONE zu.

Ich habe einige verwandte Stackoverflow-Beiträge gelesen, die sich auf Folgendes beziehen: link1 , link2 , link3 ... keiner von diesen hat mir geholfen.

Ich verwende python-2.6, Flask-Restful-0.3.3, Flask-0.10.1, Chrome, POSTMAN unter Oracle Linux 6.5.

Python-Codeapp.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 __== '__main__':
    app.run(Host='0.0.0.0', port=5444 ,debug=True)

Testen dieser mit POSTMAN:

  • form-data: funktioniert einwandfrei!
  • Verwendung von raw -> json: verursacht dieses Problem

Dinge ausprobiert # 1

json-Parameter zu meiner add_argument()-Methode in app.py hinzufügen

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

Input: {"Benutzername": "Hallo", "Passwort": "Welt"}

Output: {"p": "None", "u": "None"}

Dinge ausprobiert # 2

Ändern Sie den Typ in unicode in der add_argument()-Methode in app.py.

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: {"Benutzername": "Hallo", "Passwort": "Welt"}

Output: {"p": "None", "u": "None"}


PS: Ich werde meine Frage mit jedem fehlgeschlagenen Versuch aktualisieren. Bitte lassen Sie mich wissen, wenn Sie weitere Informationen benötigen, um diese Frage deutlicher zu machen.

17
sudhishkr

Gemäß der Dokumentation zu Request.json und dem neuen Request.get_json sollten Sie den Mimetyp Ihrer POST - Anforderung auf application/json setzen. Dies ist die einzige Möglichkeit, mit der Flask Ihre JSON-Daten automatisch in die Request.json-Eigenschaft parsen kann. 

ANMERKUNG: Die neuere get_json-Funktion hat eine Option, um die Analyse von POST -Daten unabhängig vom Mimetyp als JSON zu erzwingen

18
junnytony

junnytonys Antwort gab mir einen Hinweis, und ich ging mit diesem Ansatz weiter. get_json scheint den Trick gemacht zu haben. 

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 __== '__main__':
    app.run(Host='0.0.0.0', port=5444 ,debug=True)
8
sudhishkr

Ich bin auf ein ähnliches Problem gestoßen und hier ist eine Lösung, die für mich funktioniert. Nehmen wir an, Ihre Bewerbung sieht so aus:

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 __== '__main__':
    app.run(debug=True)

Nun können Sie einfach einige JSON-Daten erstellen:

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

und rufen Sie die Anwendung auf:

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

Dies wird mit dem Fehler abstürzen (ich habe den Traceback verkürzt):

age = args ['personal_data'] ['age']
TypeError: Das Objekt 'NoneType' kann nicht subskribiert werden

der Grund ist, dass der Header nicht angegeben ist. Wenn wir das hinzufügen 

-H "Content-Type: application/json"

und dann anrufen

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

Die Ausgabe sieht wie erwartet aus:

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

Die Funktion kann auch weiter vereinfacht werden:

class Item(Resource):

    def post(self):

        json_data = request.get_json()
        # create your response below

als oben angezeigt .

1
Cleb

Nachdem ich die Anfrage gezwungen hatte, json zu analysieren, funktionierte sie bei mir. Hier ist der Code:

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