技術と趣味となにか

ゆるくやる

FastAPIでOpenAPIスキーマを生成する

Web開発をしているとREST APIを当たり前のようにすると思いますし、大抵はバックエンドとフロントエンドの仕様共有にOpenAPIを使うと思います。

フロントエンドではよくOpenAPIから型定義の生成をしますが、そのOpenAPIも自動生成したかったりします。(OpenAPI書くのがちょっと面倒だったり、実装と乖離していたりすることがたまによくあります👼)

FastAPIはOpenAPIスキーマを生成できるPythonのWebアプリケーションフレームワークで、Pythonコードの型アノテーションを基にして、コンポーネントAPIスキーマを生成できるすごい特徴を持っています。

fastapi.tiangolo.com

普段TypeScriptを使っている身としてはTypeScriptでもFastAPIのようなものがあったらなとは思うものの、実行時には型情報が落ちるTypeScriptの悲しき定めを感じています。

Node.jsでOpenAPIが生成できるWebアプリケーションフレームワークfastify があります。こちらはプラグインJavaScriptのオブジェクトとしてスキーマ定義をすることができますが、自分でスキーマ定義はやりたくないので今回は使いませんでした。

www.fastify.io

インストールして動かす

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()

github.com

python -m uvicorn main:app

実行すると localhost で起動するサーバーでAPIを叩いたり、 /docs/openapi.json で定義したスキーマの確認ができます。

Webサーバーを起動するのとは別にスキーマを出力するために export_openapi_scheme 関数を定義・実行できるようにしています。FastAPIのissueコメントでこの方法を答えている方がいてハッピーでした。

終わり

「書いたコードから生成できるの最高や」とか言いながらやっていました。リポジトリの方には久しぶりに書いたDockerfileやMakefileも込みであげています。

github.com