0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FastAPI 型のヒントと自動変換

Last updated at Posted at 2025-04-11

はじめに

この記事は、FastAPI の型ヒントや型の自動変換について
私が気になった箇所を掘り下げた記録です。

前提知識

Pythonの基本知識
APIの基本知識

Pydantic

FastAPI では、「型ヒント」「自動変換」「APIの入出力のバリデーション」を Python のライブラリ Pydantic で行っている。

FastAPI の作者は Sebastián Ramírez で、Pydnatic の作者は Samuel Colvinですが
Sebastián Ramírez氏は Pydantic の開発にも貢献しているとのこと。1
そのため、互換性が高く Pydanticは、FastAPI にデフォルトでインストールされています。

型ヒント

Pythonは、動的型付け言語だから、型情報はなくても動きます。
しかし、明示的に型情報を定義することもできます。

class Task():
    id: int
    title: str

クラスのアノテーションで型を確認することができます。

print(Task.__annotations__)
# {'id': <class 'int'>, 'title': <class 'str'>}

ここまでで Pydantic はまだ出てきていません。型ヒントはPythonの標準機能です。
Pydnatic は Python の「型ヒント」を使って、「APIの入出力のバリデーション」を行っています。

APIの入出力のバリデーション

「APIの入出力のバリデーション」を使用するために Pydnatic をインポートします。

import pydantic

さらに、バリデーションは、Pydnatic の BaseModel クラスで行なわれます。

BaseModel = pydantic.BaseModel

これらを1行にまとめると

from pydantic import BaseModel

になります。Pythonで宣言したクラスの引数に BaseModel を
BaseModel クラスを引数にすることで BaseModel クラスが継承できます。

class Task(BaseModel):
    id: int
    title: str

型の情報は Pythonと同じくアノテーションに入っています。

print(Task.__annotations__)
# {'id': <class 'int'>, 'title': <class 'str'>}

本題のバリデーションは、Pydnatic-Coreというライブライで行われています。
Pydnatic-Core は、プログラミング言語 Rust で組まれており、以下の Github からソースコードを確認することができます。

バリデーションを行っているライブラリはわかりましたので、
Pydnatic-Core へ渡すまでの FastAPI が行っている処理を確認します。

Field で title に詳細なバリデーション、メタデータを追加しました。

from pydantic import BaseModel, Field
class Task(BaseModel):
    id: int
    title: str = Field( 
        default=None, 
        title="The description of the item", 
        max_length=300
)

今後、バリデーションを行うのに元(設計図)となるデータを
FastAPI は CoreSchema として Pydnatic-Core に渡します。

import pprint
schema = Task.__pydantic_core_schema__
pprint.pprint(schema)

CoreSchema 構造は型情報を含め、かなり細かな情報を返します。
先ほど追加した Field の情報も返しています。

'schema': {'computed_fields': [],                                            
    fields': {'id': {'metadata': {},                                           
        'schema': {'type': 'int'},                                                   
        'type': 'model-field'},
    'title': {'metadata': {'pydantic_js_updates': {
                'title': 'The description of the item'
            }},
            'schema': {'default': None,
                        'schema': {'max_length': 300, 'type': 'str'},
                        type': 'default'},
            'type': 'model-field'}},
    model_name': 'Task',
    'type': 'model-fields'},
'type': 'model'}

BaseModel の init で CoreSchema と APIの入力値 (data) を
バリデーションしています。

validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)

Rust で書かれた Pydnatic-Core をもっと掘り下げるのも良さそうですね。

自動変換

自動変換も Pydnatic-Core の validate_python 関数で行っています。
validate_python 関数は Pydnatic の TypeAdapter から呼び出せます。2

from typing import List
from pydantic import BaseModel, TypeAdapter
class Item(BaseModel):
    id: int
    name: str
    
item_data = [{'id': "1", 'name': 'My Item'}]
# [Item(id=1, name='My Item')]

変換の動作は以下のようになります。( 動作を確認済み )

入力 型ヒント 結果
"42" int 42 に変換される
"42.5" int 42.5 に変換される
"true" / "True" bool True に変換される
"false" / "False" bool False に変換される
["tag1", "tag2"] List[str]  ["tag1", "tag2"]
["1", "2"] List[int]  [1, 2]
{"x": 1, "y": 2} dict {'x': 1, 'y': 2}

Pydanticint v2 から int, float, Decimal を str ( 文字列 ) に変更することはできなくなっています。
coerce_numbers_to_str の設定を変更することで文字列への自動変換が可能になります

自動変換も Rust のコードを掘り下げるのも良さそうです。

  1. 以下のリンク先で対談が聞けます。
    https://talkpython.fm/episodes/show/415/future-of-pydantic-and-fastapi
    https://www.youtube.com/watch?v=vh0Lv-2trBQ

  2. コードは、Pydantic のサイトから参照しました。
    https://docs.pydantic.dev/2.3/usage/type_adapter/

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?