Python Flask-Restful POST not taking JSON arguments Python Flask-Restful POST not taking JSON arguments flask flask

Python Flask-Restful POST not taking JSON arguments


junnytony's answer gave me a hint, and I went ahead with this approach. get_json seems to have done the trick.

from flask import Flask, jsonify, requestfrom flask_restful import reqparse, abort, Api, Resourceapp = 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)


According to the documentation for Request.json and the new Request.get_json, you should have the mimetype on your POST request set to application/json. This is the only way flask will automatically parse your JSON data into the Request.json property which (I believe) is what Flask-Restful depends on to retrieve JSON data.

NOTE: The newer get_json function has an option to force the parsing of POST data as JSON irrespective of the mimetype


I ran into a similar issue and here is a solution that works for me. let's say your application looks like this:

from flask import Flask, jsonifyfrom flask_restful import Api, Resource, reqparseapp = Flask(__name__)api = Api(app)# Define parser and request argsparser = reqparse.RequestParser()parser.add_argument('last_name', type=str)parser.add_argument('first_name', type=str)# not the type=dictparser.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)

Now, you can easily create some JSON data:

import jsond = {'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"]}}'

and call the application:

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

This will crash with the error (I shortened the traceback):

age = args['personal_data']['age']
TypeError: 'NoneType' object is not subscriptable

the reason is that the header is not specified. If we add the

-H "Content-Type: application/json"

and then call

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

The output looks as expected:

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

The function can be also further simplified to:

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

as shown above.