ChatGPT解决这个技术问题 Extra ChatGPT

如何在 Flask 中获取 POSTed JSON?

我正在尝试使用 Flask 构建一个简单的 API,现在我想在其中读取一些 POSTed JSON。我使用 Postman Chrome 扩展程序进行 POST,而我 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"}。有谁知道我如何从中获取发布的 JSON在 Flask 方法中?


M
Martijn Pieters

首先,.json 属性是一个委托给 request.get_json() method 的属性,它记录了您在此处看到 None 的原因。

您需要将请求内容类型设置为 application/json 才能使 .json 属性和 .get_json() 方法(不带参数)正常工作,否则会产生 None。请参阅 Flask Request documentation

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

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

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


我认为当此时引发异常时,它更可能导致 500 内部错误响应,不是吗?
@iBug 这是一个老问题,但答案是它应该导致 400,因为如果请求没有格式错误,则不会引发异常。
@iBug:请求中格式错误的 JSON 不是服务器错误,而是客户端的错误,使其成为 400 类错误。
L
Luke

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

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

“json=" 输入将自动设置内容类型,如下所述:How to POST JSON data with Python Requests?

上面的客户端将使用这个服务器端代码:

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)

r
radtek

这是我会做的方式,应该是

@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

请参阅flask documentation

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

希望这可以帮助!


我看不到任何情况下有时发布有效的 json 和有时发布无效的 json 是有意义的。听起来像是两个不同的终点
就像我说的,如果端点采用“可选”json 正文,您可以使用 silent=True。是的,这是可能的,我确实使用它。它实际上基于您设计要使用的 API 的方式。如果您的端点没有这种情况,只需删除 silent=True 或将其显式设置为 False
d
davidism

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

要添加到此答案,您可以发送到此端点的请求可以是 response = request.post('http://127.0.0.1:5000/hello', json={"foo": "bar"})。在此运行 response.json() 之后应返回 {'foo': 'bar'}
A
Arcyno

对于所有问题来自 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()

请注意,由于某种原因,如果 dict 被定义为 const,例如 const foo = {hello: "world"},它将不起作用。
M
Maicon Mauricio

您可能会注意到 request.jsonrequest.get_json() 仅当 Content-type: application/json 已添加到请求的标头中时才有效。如果您无法更改客户端请求配置,则可以像这样获取正文为 json:

data = json.loads(request.data)

这对我有用,当尝试为 dialogflow webhook 编写谷歌云函数时,请求以 JSON 格式作为正文发送
Ö
Ömer Taban

给出另一种方法。

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)

d
davidism

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

request.get_json(force=True)

R
RAJAHMAD MULANI

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

u
user8045900

可以使用以下代码:

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

这是我获取 json 数据的屏幕截图:

https://i.stack.imgur.com/2uFqM.jpg

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


M
Mohammed Alhussaini

尽管我在这里遇到的所有答案都是正确的。有些事情我认为应该作为更好的做法来做。这就是我的写法。

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

C
Codemaker

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

request.get_json(force = True)