FlaskでPOSTされたJSONを取得するにはどうすればよいですか?


326

Flaskを使用して単純なAPIを構築しようとしています。ここで、POSTされたJSONを読み取ります。Postman 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を取得する方法を誰かが知っていますか?

回答:


428

まず、.json属性は、request.get_json()メソッドに委譲するプロパティであり、Noneここに表示される理由を説明しています。

あなたはへの要求のコンテンツタイプを設定する必要があるapplication/jsonため.jsonプロパティおよび.get_json()生成するかのように仕事に(引数なし)メソッドをNoneそう。FlaskのRequestドキュメントを参照してください。

MIMEタイプがJSON(アプリケーション/ json、参照is_json())を示している場合、これには解析されたJSONデータが含まれますNone。それ以外の場合はになります。

キーワード引数request.get_json()を渡すことで、コンテンツタイプの要件をスキップするように指示できforce=Trueます。

この時点で例外が発生した場合(おそらく400 Bad Request応答になる)、JSON データは無効であることに注意してください。何らかの形で不正です。JSONバリデーターで確認したい場合があります。


とき、私は思った例外がこの時点で提起されたことがない、500内部エラー応答でそれべき可能性が高い結果?
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_jsonJSON本体を取得しようとしたときに関数が黙って失敗します。デフォルトでは、これはに設定されていFalseます。常にjson本体が必要な場合(オプションではない)、そのままにしておきsilent=Falseます。

設定force=Truerequest.headers.get('Content-Type') == 'application/json'フラスコがあなたのために行うチェックを無視 します。デフォルトでは、これもに設定されていFalseます。

フラスコのドキュメントを参照してください。

私は離れforce=Falseて、クライアントにContent-Typeヘッダーを送信させて、より明示的にすることを強くお勧めします。

お役に立てれば!


2
jsonボディがオプションであるかどうかに依存するため、ケースによって異なります
radtek

2
有効なjsonを投稿したり、無効なjsonを投稿したりすることが理にかなっているケースは見当たりません。2つの異なるエンドポイントのように聞こえる
vidstige

1
私が言ったように、エンドポイントが「オプションの」jsonボディを取る場合、を使用できますsilent=True。はい、可能です。私は使用しています。これは、消費するAPIの設計方法に基づいています。エンドポイントにそのようなケースがない場合は、削除するsilent=Trueか明示的にに設定してくださいFalse
radtek、2016年

明確にするために、print(content)content = request.get_json()はオブジェクトを出力します...しかし、有効なPythonオブジェクトとして(有効なJSONオブジェクトとしてではなく)たとえば、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 2017年

{'foo': 'bar'}ただし、これは有効なJSON ではありません。JSONによく似た有効なPythonオブジェクト表現である可能性がありますが、有効なJSONは厳密に二重引用符を使用します。
Jochem Schulenklopper

@JochemSchulenklopperリクエストget_json()メソッドはJSONからPythonオブジェクトにデコードます。有効なJSONドキュメントを生成することを期待していますか?
Martijn Pieters

@MartijnPieters、私は少なくとも2度私に噛み付く特異性についての発言をしていただけです:-)しかし、はい、通常、Python dictではなく、関数が呼び出される.json().get_json()、有効なJSONオブジェクト表現を返すことが期待されます。私は名前を見ているだけで、それから何が出てくるのかを推測しています。
Jochem Schulenklopper

5

問題がajax呼び出しにあるすべての人のために、ここに完全な例があります:

Ajax呼び出し:ここでの鍵はdictJSON.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)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.