LoginSignup
90
85

More than 3 years have passed since last update.

はじめての Flask #5 ~JSONを返すWebAPIを書こう~

Last updated at Posted at 2019-08-20

前回: はじめての 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を行ったときはheaderContent-Typeapplication/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をダンプすることもできますが、こちらはheaderContent-Typetext/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を!!

90
85
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
90
85