如何在Flask中获得post JSON ?

我试图使用Flask构建一个简单的API,在其中我现在想读取一些post JSON。我用邮递员Chrome扩展做POST, JSON I POST是简单的{"text":"lalala"}。我尝试使用以下方法读取JSON:

@app.route('/api/add_message/<uuid>', methods=['GET', 'POST'])
def add_message(uuid):
content = request.json
print content
return uuid

在浏览器上,它正确地返回我放入GET中的UUID,但在控制台上,它只是打印出None(我希望它打印出{"text":"lalala"}。有人知道我如何从Flask方法中获得发布的JSON吗?

769359 次浏览

首先,.json属性是一个委托给request.get_json()方法的属性,它记录了为什么你在这里看到None

你需要将请求内容类型设置为application/json,以便.json属性和.get_json()方法(不带参数)工作,否则两者都会产生None。参见Flask Request文档:

如果mimetype表示JSON (application / json,参见is_json()),则它将包含解析的JSON数据,否则将为None

你可以通过传递force=True关键字参数来告诉request.get_json()跳过内容类型要求。

注意,如果此时引发异常(可能导致400坏请求响应),则您的JSON 数据是无效的。它在某种程度上是畸形的;你可能想用JSON验证器检查它。

我就会这么做,也应该这样

@app.route('/api/add_message/<uuid>', methods=['GET', 'POST'])
def add_message(uuid):
content = request.get_json(silent=True)
# print(content) # Do your processing
return uuid

设置了silent=True后,get_json函数在试图检索json主体时将无声地失败。默认情况下,它被设置为False。如果你总是期望json主体(不是可选的),将其保留为silent=False

设置force=True将忽略 request.headers.get('Content-Type') == 'application/json'检查烧瓶为你做。默认情况下,它也被设置为False。< / p >

看到瓶的文档

我强烈建议保留force=False,并让客户端发送Content-Type报头,使其更显式。

希望这能有所帮助!

作为参考,以下是如何从Python客户端发送json的完整代码:

import requests
res = requests.post('http://localhost:5000/api/add_message/1234', json={"mytext":"lalala"})
if res.ok:
print(res.json())

“json =“;input将自动设置内容类型,如这里讨论的:如何POST JSON数据与Python请求?

上面的客户端将与服务器端代码一起工作:

from flask import Flask, request, jsonify
app = Flask(__name__)


@app.route('/api/add_message/<uuid>', methods=['GET', 'POST'])
def add_message(uuid):
content = request.json
print(content['mytext'])
return jsonify({"uuid":uuid})


if __name__ == '__main__':
app.run(host= '0.0.0.0',debug=True)

假设你已经发布了带有application/json内容类型的有效JSON, request.json将拥有解析过的JSON数据。

from flask import Flask, request, jsonify


app = Flask(__name__)




@app.route('/echo', methods=['POST'])
def hello():
return jsonify(request.json)

给出另一种方法。

from flask import Flask, jsonify, request
app = Flask(__name__)


@app.route('/service', methods=['POST'])
def service():
data = json.loads(request.data)
text = data.get("text",None)
if text is None:
return jsonify({"message":"text not found"})
else:
return jsonify(data)


if __name__ == '__main__':
app.run(host= '0.0.0.0',debug=True)

假设您已经发布了有效的JSON,

@app.route('/api/add_message/<uuid>', methods=['GET', 'POST'])
def add_message(uuid):
content = request.json
print content['uuid']
# Return data as JSON
return jsonify(content)

对于所有那些问题来自ajax调用的人,这里有一个完整的例子:

Ajax调用:这里的关键是使用dict,然后使用JSON.stringify

    var dict = {username : "username" , password:"password"};


$.ajax({
type: "POST",
url: "http://127.0.0.1:5000/", //localhost Flask
data : JSON.stringify(dict),
contentType: "application/json",
});

在服务器端:

from flask import Flask
from flask import request
import json


app = Flask(__name__)


@app.route("/",  methods = ['POST'])
def hello():
print(request.get_json())
return json.dumps({'success':True}), 200, {'ContentType':'application/json'}


if __name__ == "__main__":
app.run()

如果使用force=True,它将忽略请求的内容类型,并尝试将主体解析为JSON。

request.get_json(force=True)

你可能会注意到,只有在请求头中添加了Content-type: application/json时,request.jsonrequest.get_json()才有效。如果你无法改变客户端请求的配置,那么你可以像这样得到json的主体:

data = json.loads(request.data)

可以使用以下代码:

@app.route('/api/add_message/<uuid>', methods=['GET', 'POST'])
def add_message(uuid):
content = request.json['text']
print content
return uuid

这是我得到json数据的截图:

enter image description here

您可以看到返回的是字典类型的数据。

尝试在get_json()方法中将force属性设置为True来解决此问题。

request.get_json(force = True)

尽管我在这里遇到的所有答案都是正确的。有一件事我认为应该做,作为更好的实践。我是这样写的。

from flask import app, request, Flask, jsonify




@app.route('/api/add_message/<uuid>', methods=['GET', 'POST'])
def add_message(uuid):
    

# Check if the request method is POST
if request.method == 'POST':
# content will return eather parse data as JSON
# Or None incase there is no data
content = request.get_json()
print(content)
# The content could be displayed in html page if serialized as json
return jsonify(content) # Return null if there is content


# if it is only get request then just return uuid
return uuid
{
"uuid":1212121212,
"text":"lalala",
"comment":"",
"signed_on":"2022-11-07 00:03:00"
}

您可以将上述数据作为json发送,并使用request.json在flask应用程序中获取它

from flask import request, Blueprint,flash,json


@app.route('/api/add_message/<uuid>', methods = ["GET", "POST"])
def testing(uuid):
sync_data = request.json
josn_data = json.dumps(sync_data ,default =str)
return josn_data