前回: はじめての Flask #4 ~データベースをSQLAlchemyでいじってみよう~
今までの学習を通して、様々なwebアプリが作れるようになったと思います。
さて、今回はいよいよJSONを返すWebAPIを作ろうと思います!
何がうれしいの
WebAPIがあると何がうれしいの?ということですが、大まかに以下の理由があげられます。
・内部処理とビュー(外面)を分けることができる
・さまざまなプラットフォームでの利用に簡単に対応することができる
・細かく処理を分けることができるので、設計自体が非常にわかりやすく、かつ組み立てやすくなる
上記の3つが主に考えられるものです。
それぞれわかりやすく説明してみましょう。
内部処理とビュー(外面)を分けることができる
今までの内容で作ったwebサービスであれば、1つのページに対して1つの動作というペアが完成していました。あるページからほかのページの内容をそのまま取得することはできず、情報の取得はページの遷移でしか行えないものでした。つまり、情報の内容とUI(HTMLなど)は切り離せない状態で返すしかなかったのです。
しかし、JSONという情報のみを扱うデータを返すことができるようになると、その情報の表現はUI次第になります。UIが古臭いならば見てくれのみ改修すればよく、セキュリティに問題があるならばWebAPIのみ変更すればよいのです。
この分離が、WebAPI最大の特徴ともいえます。
さまざまなプラットフォームでの利用に簡単に対応することができる
上記の通り、情報とUIの分離に成功すれば、UIのみそれぞれのに対応するように設計すれば、WebAPI自体はノータッチで再利用できます。
ブラウザ版も、スマホアプリ版も、どのような利用方法であったとしても内部処理は変わらないので、バックエンド開発側もフロントエンド開発側も楽に実装ができます。
細かく処理を分けることができるので、設計自体が非常にわかりやすく、かつ組み立てやすくなる
あたかもプログラム内で関数を定義するかのように、目的の動作を行うエンドポイントを作成すればその組み合わせで容易に処理が実行できます。
目的の異なるエンドポイントを複数作成する方が、互いに複雑に絡み合った長大な単一のエンドポイントを作成・保守するよりも容易なことは想像に難くないはずです。
早速作ろう!
ということで、まず大切なJSONの返し方から学んでいきましょう!
JSONの返し方
from flask import *
app = Flask(__name__)
@app.route("/")
def index():
return jsonify({"language": "python"})
if __name__ == "__main__":
app.run(port=8888)
このようにflask.jsonify
にdict型を与えるとそれをJSONにダンプしてくれますので、それを返しましょう。ちなみに、このjsonifyを行ったときはheader
のContent-Type
もapplication/json
にしてくれます。ありがとうFlask。
このページに接続すると
{"language": "python"}
というJSONを返します。
ちなみに
from flask import *
import json
app = Flask(__name__)
@app.route("/")
def index():
return json.dumps({"language": "python"})
if __name__ == "__main__":
app.run(port=8888)
のように自らjson.dumps
を使ってJSONをダンプすることもできますが、こちらはheader
のContent-Type
がtext/html; charset=utf-8
となり、みずからheader
を書き換える必要が出てくるので、flask.jsonify
を使う方が良いです。
ステータスコードも一緒に返そう!
WebAPIを作ると「認証が間違っている!!(400番)」、「お前ちょっとリクエスト送りすぎ!!(429番)」、「ごめん、エラー起きた(500番)」など、200番以外のステータスコードを返したくなることもあります(というか返しましょう)。
そのときには、エンドポイント内のreturn
で、ステータスコードの番号も一緒に返しましょう!
from flask import *
app = Flask(__name__)
@app.route("/")
def index():
return jsonify({"language": "python"}), 418
if __name__ == "__main__":
app.run(port=8888)
このようにすることで、今回であれば「I'M A TEAPOT」(418番)のステータスコードを返すことができます。
日本語を返したい!
ちなみに、flaskのflask.jsonify
では、すべての文字はデフォルトではascii
となります。ですので、日本語を返そうと以下のようなコードを書くと、不都合が起きます。
from flask import *
app = Flask(__name__)
@app.route("/")
def index():
return jsonify({"language": "パイソン"}), 418
if __name__ == "__main__":
app.run(port=8888)
帰ってくるJSONは
{"language":"\u30d1\u30a4\u30bd\u30f3"}
となります。わぁ、Unicodeだぁ…。
はい、ですので、文字コードの設定をUTF-8(asciiじゃなくする)
にしてあげましょう。
from flask import *
app = Flask(__name__)
app.config["JSON_AS_ASCII"] = False
@app.route("/")
def index():
return jsonify({"language": "パイソン"}), 418
if __name__ == "__main__":
app.run(port=8888)
このように、app.config["JSON_AS_ASCII"]
をFalse
にすることで日本語・漢字・そのほか多くの文字をJSONに正しくダンプできます。
これまでの情報と、GET
, POST
(ほかにもPUT
などのメソッドもありますが、それは他の記事に譲ります)のやり取りを組み合わせることで、WebAPIは作成できます。
それではみなさん、良いPython Lifeを!!