mcpField
P
pydantic-v2

pydantic-v2

github.com/bm629開発6117 回インストール1 週間前に更新
リポジトリ

pydantic-v2 について

Python 開発者向けに、Pydantic v2 のデータモデル作成と検証を案内するリファレンススキルです。v2 API、シリアライズ、v1 からの移行時の注意点を扱います。

主な機能

  1. 01型付きモデルとフィールド制約
  2. 02フィールドおよびモデルバリデーター
  3. 03シリアライズと計算フィールド
  4. 04環境変数と .env から設定を読み込み
  5. 05TypeAdapter とユニオン型の検証
  6. 06v1 から v2 への移行ガイド

活用シーン

  1. 01検証付き DTO や設定モデルの定義
  2. 02フィールド単位または複数フィールドの検証追加
  3. 03API やデータ交換向けのモデルシリアライズ
  4. 04環境変数からアプリ設定を読み込み

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/bm629/agent-skills --skill pydantic-v2

インストール後、Claude Code で/pydantic-v2を入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
migration-v1-to-v2.md
serialization.md
settings.md
sources.md
validators.md

詳細

Pydantic v2

概要

Pydantic v2 は、Python の型ヒントに基づいてデータを検証し、シリアライズします。BaseModel のサブクラスでは、アノテーションとしてフィールドを宣言します。インスタンスを生成すると入力が検証・変換され、model_dump* を使ってインスタンスを dict/JSON に変換できます。このスキルは、現在の v2 を記述するために必要な知識の差分、つまり v1 以降の API(model_config = ConfigDict(...)、model_dump()、@field_validator)と、v1 の慣れた書き方が残っていると陥りやすい落とし穴を扱います。スタンドアロンの Pydantic、すなわちモデル、フィールド、バリデーター、シリアライズ、設定、pydantic-settings、TypeAdapter、構造化型/ユニオン型を対象とします。フレームワークレベルのリクエスト/レスポンスモデル化と response_model については、fastapi スキルを参照してください。このスキルでは、フレームワーク固有の仕組みを重複して説明しません。

有効化するタイミング

  • ✅ 型付きフィールドと制約を持つデータモデル、設定オブジェクト、または DTO を定義するとき。
  • ✅ フィールドレベルまたはモデルレベルの検証、カスタムシリアライズ、計算フィールドを記述するとき。
  • ✅ pydantic-settings で環境変数/.env からアプリケーション設定を読み込むとき。
  • ✅ TypeAdapter でモデル以外の形状(list[Model]、dict、プリミティブ値)を一括検証するとき。
  • ✅ v1 時代のコード(class Config、.dict()、@validator)を v2 にモダナイズするとき。

有効化しないでください:

  • タスクが FastAPI のリクエスト/レスポンスの接続や response_model に関する場合は、fastapi スキルを使用してください。
  • トピックが Pydantic-AI エージェントや Logfire の計測に関する場合は、別の製品のため対象外です。

ワークフロー

ステップ 1:型ヒントでモデルを定義する

フィールドは name: Type の形式です。デフォルト値がなければ必須です。デフォルト値を指定すると省略可能になります。v2 では特に、Optional[int](つまり int | None)はフィールドを null 許容にするだけで、デフォルト値は設定しません。デフォルト値を省略した場合、フィールドは引き続き必須です。ミュータブルなデフォルト値には default_factory を使ってください(インスタンス間で共有されるリテラルの []/{} は使わないでください)。

from pydantic import BaseModel, Field

class User(BaseModel):
    id: int                                   # required
    name: str = "anon"                        # optional, has default
    nickname: str | None = None               # nullable AND optional (explicit default)
    tags: list[str] = Field(default_factory=list)  # safe mutable default

信頼できるキーワード引数(User(id=1))からインスタンスを生成するか、クラスメソッドの User.model_validate(obj)(dict/オブジェクト)および User.model_validate_json(data)(JSON の str/bytes)で信頼できない入力を検証します。model_construct(**data) は検証を省略するため、信頼できるデータにのみ使用してください。

ステップ 2:Annotated[..., Field(...)] でフィールドに制約を設定する

Annotated スタイルを優先してください。型を正確に保ち、ほかの型ときれいに組み合わせられます。Field には gt/ge/lt/le/multiple_of(数値)、min_length/max_length/pattern(文字列)のほか、default、default_factory、description、alias、exclude を指定できます。

from typing import Annotated
from pydantic import BaseModel, Field

class Account(BaseModel):
    balance: Annotated[int, Field(ge=0)]
    handle: Annotated[str, Field(min_length=3, max_length=32, pattern=r"^[a-z0-9_]+$")]
    score: Annotated[float, Field(default=0.0, le=100.0)]
ステップ 3:@field_validator/@model_validator で検証する

フィールドバリデーターはフィールドごとに実行され、モデルバリデーターはフィールドをまたいで実行されます。before/after/plain/wrap モード、ValidationInfo、および @classmethod のルールについては、references/validators.md を参照してください。

from typing_extensions import Self
from pydantic import BaseModel, field_validator, model_validator

class Signup(BaseModel):
    email: str
    password: str
    password_repeat: str

    @field_validator("email", mode="after")
    @classmethod
    def lowercase(cls, v: str) -> str:
        return v.lower()

    @model_validator(mode="after")
    def passwords_match(self) -> Self:
        if self.password != self.password_repeat:
            raise ValueError("passwords do not match")
        return self
ステップ 4:model_dump* でシリアライズする

model_dump() → dict、model_dump_json() → JSON 文字列です。include/exclude/exclude_unset/exclude_defaults/exclude_none/by_alias/mode で出力形式を調整します。@field_serializer でカスタマイズし、@computed_field で派生出力を追加できます。references/serialization.md を参照してください。

user.model_dump()                              # dict, python types
user.model_dump(exclude={"password"})          # drop a field
user.model_dump(exclude_unset=True)            # only explicitly-set fields (PATCH-style)
user.model_dump_json(by_alias=True, exclude_none=True, indent=2)
ステップ 5:model_config = ConfigDict(...) で設定する

クラス属性 model_config(ネストした class Config ではありません)に ConfigDict を設定します。よく使うオプションは、strict、from_attributes(ORM オブジェクトから読み込み)、validate_assignment、use_enum_values、extra("ignore"/"allow"/"forbid")、frozen、str_strip_whitespace です。名前によるエイリアス指定では、現在の 2.11 以降は validate_by_name=True(validate_by_alias=True と併用)を推奨します。落とし穴の項を参照してください。

from pydantic import BaseModel, ConfigDict

class Row(BaseModel):
    model_config = ConfigDict(from_attributes=True, extra="forbid", frozen=True)
    id: int
    label: str

obj = Row.model_validate(orm_row)   # from_attributes reads attributes off an ORM object
ステップ 6:pydantic-settings で設定を読み込む

BaseSettings は独立した pydantic-settings パッケージ(コアの pydantic には含まれません)にあります。環境変数や .env からフィールドを読み込みます。SettingsConfigDict で設定します。ネストされた設定やソースの優先順位については、references/settings.md を参照してください。

from pydantic_settings import BaseSettings, SettingsConfigDict

class Settings(BaseSettings):
    model_config = SettingsConfigDict(env_prefix="APP_", env_file=".env",
                                      env_file_encoding="utf-8")
    api_key: str                  # required → from APP_API_KEY
    host: str = "127.0.0.1"
    port: int = 8000              # coerced from the string env value

settings = Settings()             # reads env / .env at construction
ステップ 7:構造 — 列挙型、Literal、ユニオン、TypeAdapter

あるモデルを別のモデルのフィールド型として使用し、モデルをネストします。固定の選択肢には Enum(JSON と親和性の高い値にする場合は str, Enum を継承)または Literal を使用します。 判別可能なユニオンでは、Field(discriminator=...) を使ってタグフィールドに基づき振り分けます。モデル以外の形状(リスト、辞書、プリミティブ)は TypeAdapter で検証します。まとめて行う検証や単独の検証には、RootModel よりも v2 に適した選択肢です。

from typing import Annotated, Literal
from pydantic import BaseModel, Field, TypeAdapter

class Cat(BaseModel):
    kind: Literal["cat"]
    lives: int

class Dog(BaseModel):
    kind: Literal["dog"]
    good_boy: bool = True

class Owner(BaseModel):
    pet: Annotated[Cat | Dog, Field(discriminator="kind")]

cats = TypeAdapter(list[Cat]).validate_python([{"kind": "cat", "lives": 9}])
ステップ 8:ValidationError を処理する

model_validate* とインスタンスの構築は、入力が不正な場合に ValidationError を発生させます。 .errors() は辞書のリスト(type、loc、msg、input、url)を返し、.error_count() は件数を返します。.json() はそれらをシリアライズします。

from pydantic import ValidationError

try:
    User.model_validate({"id": "not-an-int"})
except ValidationError as e:
    for err in e.errors():
        print(".".join(map(str, err["loc"])), err["type"], err["msg"])

ルール

必ず守るルール(違反禁止):

  • v2 API のみを使用します。 model_config = ConfigDict(...)、model_dump() / model_dump_json()、model_validate() / model_validate_json()、 @field_validator / @model_validator、model_json_schema() を使用します。 class Config、.dict() / .json()、@validator / @root_validator、 .parse_obj() / .parse_raw()、.schema() は使用しないでください。
  • @field_validator の直下には @classmethod を置く必要があります。 @model_validator(mode="after") は self に対して動作するため、@classmethod は不要です。
  • Optional[x] はデフォルト値ではありません。 フィールドを省略可能にする場合は、x | None = None のように明示的に指定します。
  • 可変なデフォルト値には default_factory を使い、 [] / {} / dict() を直接指定しないでください。
  • BaseSettings は pydantic ではなく pydantic_settings からインポートします。
  • BaseModel 内のフィールド注釈に TypeAdapter を使用しないでください。 モデル以外の型の検証には、単独で使用します。

推奨事項(変更可能):

  • Field(...) をデフォルト値として割り当てるより、Annotated[T, Field(...)] を優先します。
  • 1 つのモデルをリクエストとレスポンスの両方に使い回さず、それぞれ別のモデルを用意します。
  • 頻繁に実行される処理では、TypeAdapter のインスタンスを再利用します(1 回作成し、複数回検証します)。

注意点

  • populate_by_name は廃止に向かっています。 Pydantic 2.11+ では、代わりに ConfigDict(validate_by_name=True, validate_by_alias=True) を使用します。populate_by_name は 2.x でも引き続き動作します(v3 で非推奨になる予定です)。古い 2.x では問題ありませんが、現在のバージョンでは新しい 2 つの設定を記述してください。
  • class Config は非推奨ですが、引き続き警告なく動作します。 エラーにならないため、v1 のコードは「問題なさそう」に見えても、推奨されない書き方であり、v2 のオプションも利用できません。model_config = ConfigDict(...) に置き換えてください。
  • @field_validator に @classmethod を付け忘れると、 クラス定義時にエラーになったり、正しく動作しなかったりします。デコレーターは上から @field_validator(...)、その直下に @classmethod の順にします。
  • model_config に通常の dict を使うと動作しますが、型チェッカーの支援が失われます。 IDE や ty / mypy でキーを検証できるよう、ConfigDict(...) コンストラクターを使用してください。
  • 緩やかな型変換には注意してください。 デフォルトでは "123" は 123 に変換されます。厳密な検証が必要な場合は、ConfigDict(strict=True)(またはフィールドごとに Field(strict=True))を設定します。
  • exclude_unset と exclude_defaults は異なります。 exclude_unset は呼び出し元が設定していないフィールドを除外します(PATCH のリクエストボディに最適です)。exclude_defaults は、設定済みであってもデフォルト値と等しいフィールドを除外します。両者は置き換え可能ではありません。

アンチパターン

  • 「小さなモデルだから、古い .dict() を使おう。」 いいえ。.dict() は実質的に削除済みで、非推奨です。model_dump() を使ってください。v1 と v2 の書き方を混在させることは、Pydantic コードが壊れる主な原因です。
  • 「覚えているから」と @root_validator を使うこと。 v2 には存在しません。@model_validator(mode="before"|"after") を使用してください。
  • リストや辞書を検証するために、単純な型をフィールド 1 つだけの RootModel で包むこと。 代わりに TypeAdapter(list[T]) を使用してください。
  • FastAPI のリクエスト/レスポンス処理をここで再実装すること。 それは fastapi スキルの役割です。このスキルではモデルを定義し、フレームワークがそれを利用します。

出力

ConfigDict、型付きフィールドと制約付きフィールド、@field_validator/@model_validator による検証、model_dump* によるシリアル化、pydantic-settings の設定クラス、TypeAdapter/判別可能なユニオン構造を使用した、正確で最新の Pydantic v2 ソースです。v1 時代のイディオムは一切含みません。利用者は、検証可能でシリアル化可能なデータモデルを必要とするあらゆるコードやワークフローのフェーズです。これらのモデルが HTTP API の基盤となる場合、フレームワークとの連携には fastapi スキルを使用します。

関連項目

  • fastapi — フレームワーク固有の内容:リクエスト/レスポンスモデル、response_model、依存性注入による検証。このスキルではモデルを定義し、fastapi がそれを使用します。ここではフレームワークの仕組みを重複して説明しないでください。
  • 公式ドキュメント(出典):references/sources.md を参照してください。

段階的な開示

詳細は references/ にあり、必要に応じて読み込みます。

  • references/validators.md — バリデーターを作成する場合に読み込みます。すべての @field_validator/@model_validator のモード、ValidationInfo、@classmethod のルール、before/after の実行順序を扱います。
  • references/serialization.md — 出力をカスタマイズする場合に読み込みます。model_dump* のすべてのキーワード引数、@field_serializer、@model_serializer、@computed_field、エイリアスの種類(validation_alias/serialization_alias/AliasChoices)を扱います。
  • references/settings.md — pydantic-settings の詳細を確認する場合に読み込みます。ネストされた設定、env_nested_delimiter、ソースの優先順位、secrets_dir を扱います。
  • references/migration-v1-to-v2.md — v1 のコードを最新化する場合に読み込みます。名称変更の完全な一覧と動作の変更を扱います。
  • references/sources.md — 調査の出典です。

本文の上限

  • description は 1,024 文字以下(遵守済み)。
  • 本文は約 290 行で、5,000 トークンのソフト上限を大幅に下回ります。
  • 各リファレンスファイルは、警告のしきい値である 10k トークンを大幅に下回ります。

コメント