Python Flask-Restful POST does not accept JSON arguments

I am very new to Flask (& Flask-Restful).

My problem: json arguments for POST get NONE (not working).

I can take arguments from form-data using the POSTMAN plugin for chrome. But when I switch to raw (& feed a json ), it cannot read json and assigns NONE all my arguments.

I read some related stackoverflow posts related to this: link1 , link2 , link3 ... none of this helped me.

I am using python-2.6 , Flask-Restful-0.3.3 , Flask-0.10.1 , Chrome , POSTMAN on Oracle Linux 6.5.

Python code 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) 

Testing this with POSTMAN :

  • Using form-data : works great!
  • Using raw json : causes this problem

Proven Things # 1 :

Add json parameter to my add_argument() method in app.py

 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": "None", "u": "None"}

Proven Things # 2 :

Change type to unicode in add_argument() 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 : {"username": "hello", "password": "world"}

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


PS: I will constantly update my question with every failed attempt. Please let me know if you need more information to make this question more clear.

+18
json python rest flask flask-restful
source share
4 answers

As per the documentation for Request.json and the new Request.get_json , you should have the mimetype type in your POST request set to application/json . This is the only way the checkbox automatically parses your JSON data in the Request.json property, which, it seems to me, depends on the fact that Flask-Restful depends on the receipt of JSON data.

NOTE. The newer get_json function has the ability to force the analysis of POST data as JSON regardless of the mimetype type

+20
source share
The answer to junnytony gave me a hint, and I continued with this approach. get_json seems to have done the trick.
 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) 
+9
source share

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

 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) 

Now you can easily create some JSON data:

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

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 fail (I cut the trace):

age = args ['personal_data'] ['age']
TypeError: 'NoneType' object cannot be signed

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

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

This function can also be further simplified to:

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

as shown above .

+2
source share

After forcing the json parsing request, it worked for me. Here is the 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) 
0
source share

All Articles