FastAPIでOpenAPIスキーマを生成する
Web開発をしているとREST APIを当たり前のようにすると思いますし、大抵はバックエンドとフロントエンドの仕様共有にOpenAPIを使うと思います。
フロントエンドではよくOpenAPIから型定義の生成をしますが、そのOpenAPIも自動生成したかったりします。(OpenAPI書くのがちょっと面倒だったり、実装と乖離していたりすることがたまによくあります👼)
FastAPIはOpenAPIスキーマを生成できるPythonのWebアプリケーションフレームワークで、Pythonコードの型アノテーションを基にして、コンポーネントやAPIのスキーマを生成できるすごい特徴を持っています。
普段TypeScriptを使っている身としてはTypeScriptでもFastAPIのようなものがあったらなとは思うものの、実行時には型情報が落ちるTypeScriptの悲しき定めを感じています。
Node.jsでOpenAPIが生成できるWebアプリケーションフレームワークで fastify があります。こちらはプラグインでJavaScriptのオブジェクトとしてスキーマ定義をすることができますが、自分でスキーマ定義はやりたくないので今回は使いませんでした。
インストールして動かす
Python(3.10.6)そのもののインストールだったりエディタのLanguage Serverを入れたり色々しましたが、ここでは省きます。
pip install fastapi "uvicorn[standard]"
ソースコードは本当に何でもよかったですが、TypeScriptの型生成をするときに問題になりがちなEnumや日付文字列を返すAPIにしています。(この記事とは関係ないところで使いたい)
import datetime from enum import Enum import json from fastapi import FastAPI from fastapi.openapi.utils import get_openapi from pydantic import BaseModel app = FastAPI() class Type(Enum): JSON = 1 YAML = 2 PLAIN = 3 class Message(BaseModel): message: str date: datetime.datetime type: Type @app.get("/", response_model=Message) async def root(): return { "message": "Hello, World!", "date": datetime.datetime.now(), "type": Type.JSON } def export_openapi_scheme(): with open('openapi/openapi.json', 'w') as file: json.dump(get_openapi( title=app.title, version=app.version, openapi_version=app.openapi_version, description=app.description, routes=app.routes, ), file) export_openapi_scheme()
python -m uvicorn main:app
実行すると localhost で起動するサーバーでAPIを叩いたり、 /docs
や /openapi.json
で定義したスキーマの確認ができます。
Webサーバーを起動するのとは別にスキーマを出力するために export_openapi_scheme
関数を定義・実行できるようにしています。FastAPIのissueコメントでこの方法を答えている方がいてハッピーでした。
終わり
「書いたコードから生成できるの最高や」とか言いながらやっていました。リポジトリの方には久しぶりに書いたDockerfileやMakefileも込みであげています。