You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5.3 KiB

入力と出力でOpenAPIのスキーマを分けるかどうか

Pydantic v2 のリリース以降、生成される OpenAPI は以前より少し正確で、より正しいものになりました。😎

実際には、場合によっては同じ Pydantic モデルに対して、入力用と出力用で OpenAPI に 2 つの JSON Schema が含まれることがあります。これは デフォルト値 の有無に依存します。

その動作と、必要に応じての変更方法を見ていきます。

入出力のPydanticモデル

次のようにデフォルト値を持つ Pydantic モデルがあるとします。

{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *}

入力用モデル

このモデルを次のように入力として使うと:

{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *}

...description フィールドは 必須ではありません。デフォルト値が None だからです。

ドキュメントでの入力モデル

ドキュメントで確認すると、description フィールドには 赤いアスタリスク が付いておらず、必須としてはマークされていません:

出力用モデル

しかし同じモデルを次のように出力として使う場合:

{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *}

...description にデフォルト値があるため、そのフィールドに何も返さなくても、その デフォルト値 が入ります。

出力のレスポンスデータ

ドキュメントから試してレスポンスを確認すると、コードでは一方の description フィールドに何も追加していないにもかかわらず、JSON レスポンスにはデフォルト値(null)が含まれています:

つまりそのフィールドには 常に値があります。値が None(JSON では null)になることがあるだけです。

したがって、この API を使うクライアントは値の有無を確認する必要がなく、フィールドが 常に存在する と仮定できます。場合によってはデフォルト値の None になるだけです。

これを OpenAPI で表現するには、そのフィールドを 必須 としてマークします。常に存在するためです。

このため、モデルの JSON Schema は、入力か出力か によって異なる場合があります:

  • 入力 では description必須ではない
  • 出力 では 必須(値は None、JSON では null の可能性あり)

ドキュメントでの出力モデル

ドキュメントで出力モデルを見ると、namedescription両方赤いアスタリスク必須 としてマークされています:

ドキュメントでの入力・出力モデル

さらに、OpenAPI に含まれる利用可能なスキーマ(JSON Schema)を確認すると、Item-InputItem-Output の 2 つがあることが分かります。

Item-Input では、description必須ではありません(赤いアスタリスクなし)。

一方、Item-Output では、description必須(赤いアスタリスクあり)です。

この Pydantic v2 の機能により、API ドキュメントはより 正確 になり、自動生成されたクライアントや SDK もより正確になります。これにより、より良い 開発者エクスペリエンス と一貫性が得られます。🎉

スキーマを分けない

一方で、入力と出力で同じスキーマ にしたい場合もあります。

主なユースケースは、すでに自動生成されたクライアントコードや SDK があり、まだそれらをすべて更新したくない場合です。いずれは更新したいとしても、今ではないかもしれません。

その場合は、FastAPI のパラメータ separate_input_output_schemas=False でこの機能を無効化できます。

/// info | 情報

separate_input_output_schemas のサポートは FastAPI 0.102.0 で追加されました。🤓

///

{* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *}

ドキュメントで入力・出力に同一スキーマを使用

これでモデルの入力と出力は単一のスキーマ、Item のみになり、description必須ではありません: