Làm thế nào để có được JSON POST trong Flask?


326

Tôi đang cố gắng xây dựng một API đơn giản bằng Flask, trong đó bây giờ tôi muốn đọc một số JSON được đăng. Tôi thực hiện POST với tiện ích mở rộng Postman Chrome và JSON I POST đơn giản {"text":"lalala"}. Tôi cố gắng đọc JSON bằng phương pháp sau:

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

Trên trình duyệt, nó trả về chính xác UUID mà tôi đã đặt trong GET, nhưng trên bảng điều khiển, nó chỉ in ra None(nơi tôi mong đợi nó sẽ in ra {"text":"lalala"}. Có ai biết làm thế nào tôi có thể lấy JSON được đăng từ bên trong phương thức Flask không?

Câu trả lời:


428

Trước hết, .jsonthuộc tính là một thuộc tính ủy nhiệm cho request.get_json()phương thức , tài liệu này tại sao bạn thấy Noneở đây.

Bạn cần đặt loại nội dung yêu cầu thành application/jsonthuộc .jsontính và .get_json()phương thức (không có đối số) để hoạt động vì sẽ tạo ra Nonecách khác. Xem tài liệu FlaskRequest :

Điều này sẽ chứa dữ liệu JSON được phân tích cú pháp nếu mimetype chỉ ra JSON ( application / json , xem is_json()), nếu không nó sẽ như vậy None.

Bạn có thể request.get_json()yêu cầu bỏ qua yêu cầu loại nội dung bằng cách chuyển cho nó force=Trueđối số từ khóa.

Lưu ý rằng nếu một ngoại lệ được nêu ra tại thời điểm này (có thể dẫn đến phản hồi Yêu cầu xấu 400), dữ liệu JSON của bạn không hợp lệ. Đó là một cách nào đó dị hình; bạn có thể muốn kiểm tra nó bằng trình xác nhận JSON.


Tôi đã nghĩ rằng khi một ngoại lệ được nêu ra vào thời điểm này thì nhiều khả năng nó sẽ dẫn đến phản hồi Lỗi nội bộ 500, phải không?
iBug

100

Để tham khảo, đây là mã hoàn chỉnh về cách gửi json từ máy khách Python:

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

Đầu vào "json =" sẽ tự động đặt loại nội dung, như được thảo luận ở đây: Đăng JSON bằng Yêu cầu Python

Và ứng dụng khách trên sẽ hoạt động với mã phía máy chủ này:

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

Đây là cách tôi sẽ làm và nó nên

@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

Với silent=Truethiết lập, get_jsonchức năng sẽ thất bại âm thầm khi cố gắng lấy cơ thể json. Theo mặc định, điều này được đặt thành False. Nếu bạn luôn mong đợi một cơ thể json (không phải tùy chọn), hãy để nó như silent=False.

Cài đặt force=Truesẽ bỏ qua request.headers.get('Content-Type') == 'application/json'kiểm tra mà bình làm cho bạn. Theo mặc định, điều này cũng được đặt thành False.

Xem tài liệu về bình .

Tôi thực sự khuyên bạn nên để lại force=Falsevà làm cho khách hàng gửi Content-Typetiêu đề để làm cho nó rõ ràng hơn.

Hi vọng điêu nay co ich!


2
Tùy thuộc vào cơ thể json là tùy chọn hay không, vì vậy tùy thuộc vào trường hợp của bạn
radtek

2
Tôi không thể thấy bất kỳ trường hợp nào có ý nghĩa đối với một số lần đăng json hợp lệ và lần khác json không hợp lệ. Âm thanh như hai điểm kết thúc khác nhau
vidstige

1
Giống như tôi đã nói, nếu một điểm cuối có cơ thể json "tùy chọn", bạn có thể sử dụng silent=True. Vâng, điều này là có thể, và tôi sử dụng nó. Nó thực sự dựa trên cách bạn thiết kế API của mình sẽ được sử dụng. Nếu không có trường hợp nào như vậy cho điểm cuối của bạn, chỉ cần xóa silent=Truehoặc đặt rõ ràng thành False.
radtek

Để rõ ràng, print(content)sau khi content = request.get_json()in đối tượng ... nhưng là một đối tượng Python hợp lệ (và không phải là một đối tượng JSON hợp lệ). Ví dụ, nó sử dụng các trích dẫn đơn trong khi JSON yêu cầu nghiêm ngặt các trích dẫn kép cho cả các giá trị khóa (chuỗi) làm giá trị chuỗi. Nếu bạn muốn biểu diễn JSON, hãy sử dụng json.dumps()với đối tượng.
Joool Schulenklopper

24

Giả sử bạn đã đăng JSON hợp lệ với application/jsonloại nội dung, request.jsonsẽ có dữ liệu JSON được phân tích cú pháp.

from flask import Flask, request, jsonify

app = Flask(__name__)


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

3
Để thêm vào câu trả lời này, yêu cầu bạn có thể gửi đến điểm cuối này có thể là response = request.post('http://127.0.0.1:5000/hello', json={"foo": "bar"}). Sau khi chạy, response.json()nên quay lại{'foo': 'bar'}
ScottMcC

Có thể lưu ý rằng {'foo': 'bar'}JSON không hợp lệ mặc dù. Nó có thể là một biểu diễn đối tượng Python hợp lệ trông rất giống JSON, nhưng JSON hợp lệ sử dụng đúng dấu ngoặc kép.
Joool Schulenklopper

@JochemSchulenklopper get_json()phương thức yêu cầu giải mã từ JSON sang các đối tượng Python, vâng. Nơi bạn mong đợi nó tạo ra một tài liệu JSON hợp lệ?
Martijn Pieters

@MartijnPieters, tôi vừa đưa ra tuyên bố về một đặc thù khiến tôi ít nhất hai lần :-) Nhưng vâng, thông thường tôi mong đợi một hàm được gọi .json()hoặc .get_json()trả về một đại diện đối tượng JSON hợp lệ, không phải là một lệnh Python. Tôi chỉ nhìn vào cái tên, và suy ra những gì có thể phát sinh từ nó.
Joool Schulenklopper

5

Đối với tất cả những người có vấn đề từ cuộc gọi ajax, đây là một ví dụ đầy đủ:

Cuộc gọi Ajax: chìa khóa ở đây là sử dụng một dictvà sau đó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",
    });

Và về phía máy chủ:

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
Đây là điều làm việc cho tôi, cảm ơn rất nhiều! :)
vjjj

1

Để đưa ra một cách tiếp cận khác.

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

Giả sử rằng bạn đã đăng JSON hợp lệ,

@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

Cố gắng sử dụng tham số lực lượng ...

request.get_json(force = True)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.