如何在Flask中获取POST JSON?


326

我正在尝试使用Flask构建一个简单的API,现在我想在其中读取一些POSTed JSON。我使用Postman Chrome扩展程序执行POST,而我发布的JSON就是{"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吗?

Answers:


427

首先,该.json属性是一个委托给request.get_json()method的属性,该属性记录了为什么None在此处看到。

您需要将请求内容类型设置为,application/json以使.json属性和.get_json()方法(不带参数)起作用,None否则两者都会产生这种情况。请参阅Flask Request文档

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

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

请注意,如果此时引发异常(可能导致400 Bad Request响应),则您的JSON 数据无效。它在某种程度上畸形;您可能需要使用JSON验证程序进行检查。


我认为在此时引发异常时,它更有可能导致500 Internal Error响应,不是吗?
iBug

100

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

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

“ json =“输入将自动设置内容类型,如下所述:使用Python请求发布JSON

以上客户端将使用此服务器端代码:

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)

71

这就是我要做的方法,应该是

@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

请参见烧瓶文档

我强烈建议您离开force=False并让客户端发送Content-Type标头以使其更加明确。

希望这可以帮助!


2
取决于json主体是否可选,所以取决于您的情况
radtek

2
我看不到任何情况下有时发布有效的json而有时发布无效的json的情况。听起来像是两个不同的终点
vidstige '16

1
就像我说的那样,如果端点采用“可选”的json主体,则可以使用silent=True。是的,这是可能的,我确实使用它。它实际上是基于您如何设计要使用的API的。如果端点没有这种情况,只需删除silent=True或将其显式设置为即可False
radtek

为了清楚起见,print(content)after会content = request.get_json()打印对象...,但会打印为有效的Python对象(而不是有效的JSON对象)。例如,它使用单引号,而JSON严格要求两个键值(字符串)均使用双引号作为字符串值。如果需要JSON表示形式,请json.dumps()与对象一起使用。
Jochem Schulenklopper

24

假设您已发布具有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)

3
要添加到此答案中,您可以发送到此端点的请求可能是response = request.post('http://127.0.0.1:5000/hello', json={"foo": "bar"})。跑步之后response.json()应该会返回{'foo': 'bar'}
ScottMcC

应该指出的{'foo': 'bar'}是,这不是有效的JSON。它可能是看起来像JSON的有效Python对象表示形式,但有效JSON严格使用双引号。
Jochem Schulenklopper

@JochemSchulenklopper是将请求get_json()方法 JSON 解码为Python对象的方法。您希望它在哪里产生有效的JSON文档?
马丁·彼得斯

@MartijnPieters,我只是在做一个关于特性的声明,至少让我难过两次:-)但是,是的,通常我期望一个名为.json().get_json()返回有效JSON对象表示的函数,而不是Python dict。我只是在看这个名字,然后推断出它的名字。
Jochem Schulenklopper

5

对于所有问题都是来自ajax调用的人,这里有一个完整的示例:

Ajax调用:这里的关键是使用a 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()

1
这是对我有用的东西,非常感谢!:)
vjjj

1

给出另一种方法。

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)

0

假设您发布了有效的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)

0

尝试使用力参数...

request.get_json(force = True)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.