Python Flask-Restful POST not taking JSON arguments
Solution 1
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
Solution 2
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, 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)
Solution 3
After forcing the request to parse json, it worked with 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)
Solution 4
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, 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 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.
sudhishkr
Updated on May 23, 2020Comments
-
sudhishkr almost 4 years
I am very new to Flask (& Flask-Restful).
My problem :
json
arguments for aPOST
is getting set toNONE
(not working).I am able to take arguments from the
form-data
, usingPOSTMAN
plugin for chrome. But, when i switch toraw
(& feed ajson
), it fails to read the json & assigns aNONE
to all my arguments.I have read some related stackoverflow posts related to this : link1, link2, link3 ... none of these 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 using
POSTMAN
:- Using
form-data
: works perfectly ! - Using
raw
->json
: causes this issue
Things tried #1 :
Add
json
parameter to myadd_argument()
method inapp.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" }Things tried #2 :
Change type to
unicode
inadd_argument()
method inapp.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 keep updating my question, with every failed attempt. Please let me know if you need any more info to make this question more clear.
-
junnytony almost 9 yearsLooks to me like you're missing a call to
parser.parse_args()
. You should haveargs = parser.parse_args()
before you can access theargs
-
sudhishkr almost 9 years@junnytony - its a typo from my side, i forgot to copy that line. Editing the question right away!
-
sirfz almost 9 yearsTry
unicode
instead ofstr
for the arguments types -
sudhishkr almost 9 years@Sir_FZ
unicode
has the same issue, retainsNone
- Using
-
junnytony almost 9 yearsNice :). but I think your code would be even more awesome if you changed the mimetype for your post to be 'application/json'. I'm guessing you're using AJAX for your post. With something like jQuery you can easily add the appropriate mimetype for example stackoverflow.com/questions/6323338/…
-
Brian Wylie almost 9 yearsThanks for providing your final code, I have a similar use case.
-
KCN almost 7 yearsHI, I am also facing the same issue.As per your suggestion I done but still getting bad request error
-
sudhishkr almost 7 yearswhat your exact issue @KCN?
-
KCN almost 7 yearsAs per your suggestion I followed like json_dat = request.get_json(force=True) fname = json_dat["firstname"] lname = json_dat["lastname"] but while executing this url from rest client getting 400 bad request error