วิธีรับ JST POSTed ใน Flask


326

ฉันพยายามสร้าง API อย่างง่ายโดยใช้ Flask ซึ่งตอนนี้ฉันต้องการอ่าน JST POSTed ฉันทำโพสต์ที่มีนามสกุล Postman Chrome และ JSON {"text":"lalala"}ผมโพสต์เป็นเพียง ฉันพยายามอ่าน JSON โดยใช้วิธีการต่อไปนี้:

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

ในเบราว์เซอร์จะส่งคืน UUID ที่ฉันใส่ใน GET อย่างถูกต้อง แต่บนคอนโซลมันเพิ่งพิมพ์ออกมาNone(ที่ฉันคาดว่าจะพิมพ์ออกมา{"text":"lalala"}ใครรู้วิธีที่ฉันสามารถรับ JSON ที่โพสต์จากภายในวิธีการ Flask?

คำตอบ:


427

ก่อนอื่น.jsonแอตทริบิวต์เป็นคุณสมบัติที่มอบให้กับrequest.get_json()วิธีการซึ่งเอกสารเหตุผลที่คุณเห็นNoneที่นี่

คุณต้องตั้งค่าประเภทเนื้อหาขอเป็นเพื่อapplication/jsonให้.jsonคุณสมบัติและ.get_json()วิธีการ (โดยไม่มีข้อโต้แย้ง) ในการทำงานตามที่ทั้งสองจะผลิตเป็นNoneอย่างอื่น ดูเอกสารประกอบขวดRequest :

สิ่งนี้จะมีข้อมูล JSON ที่วิเคราะห์คำหาก mimetype ระบุว่า JSON ( application / json , see is_json()) มิฉะนั้นจะเป็นNoneเช่นนั้น

คุณสามารถบอกrequest.get_json()ให้ข้ามข้อกำหนดประเภทเนื้อหาโดยส่งผ่านforce=Trueอาร์กิวเมนต์คำหลัก

โปรดทราบว่าหากมีการยกเว้นถูกยกขึ้นที่จุดนี้ (อาจจะส่งผลให้การตอบสนองที่ 400 ร้องขอไม่ถูกต้อง) JSON ของข้อมูลที่ไม่ถูกต้อง มันมีบางอย่างผิดรูปแบบ; คุณอาจต้องการตรวจสอบด้วยเครื่องมือตรวจสอบ JSON


ฉันคิดว่าเมื่อมีข้อยกเว้นเกิดขึ้น ณ จุดนี้น่าจะส่งผลให้เกิดการตอบสนองข้อผิดพลาดภายใน 500 ครั้งใช่หรือไม่
iBug

100

สำหรับการอ้างอิงต่อไปนี้เป็นรหัสที่สมบูรณ์สำหรับวิธีการส่ง json จากไคลเอนต์ Python:

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

อินพุต "json =" จะตั้งค่าประเภทเนื้อหาโดยอัตโนมัติตามที่อธิบายไว้ที่นี่: โพสต์ 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)

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

1
เหมือนที่ผมกล่าวว่าถ้าปลายทางจะใช้เวลา "ตัวเลือก" ร่างกาย JSON silent=Trueคุณสามารถใช้ ใช่เป็นไปได้และฉันจะใช้มัน มันขึ้นอยู่กับว่าคุณออกแบบ API ของคุณอย่างไร หากมีกรณีเช่นว่าปลายทางของคุณไม่เพียง แต่เอาหรืออย่างชัดเจนตั้งค่าให้silent=True False
radtek

เพื่อความชัดเจนprint(content)หลังจากcontent = request.get_json()พิมพ์วัตถุ ... แต่เป็นวัตถุ Python ที่ถูกต้อง (และไม่ใช่วัตถุ JSON ที่ถูกต้อง) ตัวอย่างเช่นมันใช้เครื่องหมายคำพูดเดี่ยวในขณะที่ JSON ต้องใช้เครื่องหมายคำพูดคู่สำหรับทั้งค่าคีย์ (สตริง) เป็นค่าสตริงอย่างเคร่งครัด หากคุณต้องการตัวแทน JSON ใช้json.dumps()กับวัตถุ
Jochem Schulenklopper

24

สมมติว่าคุณโพสต์ JSON ที่ถูกต้องกับapplication/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 ที่ถูกต้อง อาจเป็นการแสดงวัตถุ Python ที่ถูกต้องที่ดูเหมือน JSON มาก แต่ JSON ที่ถูกต้องจะใช้เครื่องหมายคำพูดคู่อย่างเคร่งครัด
Jochem Schulenklopper

@JochemSchulenklopper get_json()วิธีการร้องขอถอดรหัสจาก JSON ไปยังวัตถุ Python ใช่ คุณคาดหวังให้ผลิตเอกสาร JSON ที่ถูกต้องได้ที่ไหน
Martijn Pieters

@MartijnPieters ฉันเพิ่งสร้างคำแถลงเกี่ยวกับความผิดปกติที่ทำให้ฉันอย่างน้อยสองครั้ง :-) แต่ใช่โดยปกติฉันคาดหวังว่าฟังก์ชั่นที่เรียกว่า.json()หรือ.get_json()ส่งกลับการแสดงวัตถุ JSON ที่ถูกต้องไม่ใช่ Python dict ฉันแค่ดูที่ชื่อและอนุมานว่าอะไรจะเกิดขึ้น
Jochem Schulenklopper

5

สำหรับทุกคนที่มีปัญหามาจากการโทร 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()

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)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.