---
title: "Pydantic Fieldの使い方：default_factory・alias・制約の引数一覧とOpenAPIへの反映【2.14対応】"
url: "https://www.issoh.co.jp/tech/details/19771/"
published: 2026-11-14
updated: 2026-11-14
categories: ["開発"]
publisher: "株式会社一創"
---

# Pydantic Fieldの使い方：default\_factory・alias・制約の引数一覧とOpenAPIへの反映【2.14対応】

PydanticのField()は、BaseModelの各フィールドに既定値、入力の制約、別名、説明文を付けるための関数です。`quantity: int = Field(gt=0, le=100)`と書けば、0以下や101以上の値は`ValidationError`になり、同じ条件がJSON Schemaの`exclusiveMinimum`と`maximum`にも出力されます。この記事では、2026年11月時点の最新版pydantic 2.14.3で指定できる引数を用途別に整理し、`default_factory`とaliasの使い分け、Annotatedでの使い回し、FastAPIのSwagger UIへの反映までをコードで示す構成です。v1の`regex`や`min_items`がv2で出すエラーと置き換え先も扱います。

## まとめ：Pydantic Fieldで押さえる引数と書き方の結論

Field()の引数は30を超えますが、実務で毎回使うのは`default_factory`、`gt`・`ge`などの数値制約、`max_length`、`pattern`、`alias`、`description`の6つです。残りは必要になった場面で引けば足ります。

呼び出すたびに値が変わる既定値（現在時刻やUUID）は`default_factory`で渡します。同じ制約を複数のモデルで使うなら、`Annotated[int, Field(gt=0)]`を型エイリアスにして1か所で定義するのが保守しやすい形です。

Fieldに書いた制約と説明は、そのままJSON SchemaとFastAPIのOpenAPIに出力されます。API仕様書を手で書かず、モデルの定義を仕様の正本にできる点がFieldを書く一番の理由です。

## Pydantic 2.14のField()で指定できる引数一覧と書き方の基本形

まずは引数の全体像と、Fieldを書く2通りの形式を確認します。[PyPIのpydantic](https://pypi.org/project/pydantic/)では、2026年11月14日時点の最新が2.14.3（11月5日公開・Python 3.10以上）です。

### Field()の引数を用途別に整理した一覧表と最初に覚える6つ

[v2.14.3のfields.py](https://github.com/pydantic/pydantic/blob/v2.14.3/pydantic/fields.py)にあるField()の定義から、引数を用途で分けると次の表になります。

| 用途       | 主な引数                        |
| -------- | --------------------------- |
| 既定値      | default、default\_factory    |
| 数値の制約    | gt、ge、lt、le、multiple\_of    |
| 長さの制約    | min\_length、max\_length     |
| 正規表現     | pattern                     |
| 小数の制約    | max\_digits、decimal\_places |
| 別名（入出力）  | alias                       |
| 別名（入力のみ） | validation\_alias           |
| 別名（出力のみ） | serialization\_alias        |
| スキーマの説明  | description、examples        |
| 出力の制御    | exclude、exclude\_if、repr    |
| 型と変更の制御  | strict、frozen               |
| 既定値の検証   | validate\_default           |
| 廃止の告知    | deprecated                  |

このほか、項目名を表す`title`、dataclass向けの`init`・`kw_only`、Unionの判別に使う`discriminator`があります。最初に覚えるのは、まとめで挙げた6つで十分です。`BaseModel`そのものの書き方は[Pydanticの読み方・BaseModelの使い方とV1との違い](https://www.issoh.co.jp/tech/details/4838/)で整理しています。

### 代入形式とAnnotated形式の違いと型エイリアスで制約を使い回す方法

Fieldは`name: str = Field(max_length=50)`の代入形式と、`Annotated`の中に置く形式のどちらでも書けます。[公式のFieldsの解説](https://pydantic.dev/docs/validation/latest/concepts/fields/)が勧めるのはAnnotated形式です。代入形式は既定値があるように見えるうえ、制約を型として切り出せません。

```
from typing import Annotated

from pydantic import BaseModel, Field

# 制約を型エイリアスにまとめ、複数のモデルで使い回す
ProductCode = Annotated[str, Field(pattern=r"^[A-Z]{3}-\d{4}$", examples=["ABC-0001"])]
Quantity = Annotated[int, Field(gt=0, le=100)]


class OrderLine(BaseModel):
    code: ProductCode
    quantity: Quantity = 1  # 既定値は代入で書く


class StockMove(BaseModel):
    code: ProductCode
    quantity: Quantity
```

注意点は1つです。`default`・`default_factory`・`alias`の3つは、mypyなどの型チェッカーが`__init__`の引数を判断する材料に使うため、Annotatedの中ではなく代入形式で書きます。Annotatedの中に書いても実行はできますが、エディタが必須項目と誤認して警告を出します。

## default\_factoryと既定値で必須・任意を決める書き方と落とし穴

既定値の書き方は、そのフィールドが必須か任意かを決めます。ここで誤ると、APIが受け付けるべき入力を422で弾く不具合になります。

### Field(…)とNone既定値の違いとOptionalだけでは任意にならない理由

既定値を書かないフィールドは必須です。`Field(...)`の`...`（Ellipsis）も必須を表しますが、既定値を省略した場合と意味は同じで、今は書く必要がありません。

見落としやすいのは`str | None`の扱いです。v1では`Optional[str]`と書くだけで既定値`None`の任意項目になりましたが、v2では「Noneも受け付ける必須項目」になります。項目ごと省略させたいなら`nickname: str | None = None`と既定値まで書きます。

既定値そのものは、既定では検証されません。[v2.14.3のconfig.py](https://github.com/pydantic/pydantic/blob/v2.14.3/pydantic/config.py)でも`validate_default`の既定は`False`です。`port: int = "abc"`と書いても起動時には止まらないため、既定値も検証したいフィールドには`Field(validate_default=True)`を付けます。

### datetime.nowをdefault\_factoryで渡す理由とリスト既定値の扱い

`created_at: datetime = datetime.now()`と書くと、`datetime.now()`はクラスを定義した瞬間に1回だけ実行されます。その後に作るインスタンスはすべて同じ時刻を持ち、ログの作成日時がプロセスの起動時刻で揃う、という不具合になります。

```
from datetime import datetime
from uuid import UUID, uuid4

from pydantic import BaseModel, Field


class Order(BaseModel):
    id: UUID = Field(default_factory=uuid4)
    created_at: datetime = Field(default_factory=datetime.now)
    tags: list[str] = []  # 可変の既定値でもインスタンスごとに複製される
```

`default_factory`には呼び出す関数そのもの（括弧なしの`datetime.now`）を渡します。インスタンスを作るたびに呼ばれ、毎回新しい値が入ります。

一方、`tags: list[str] = []`はPydanticでは問題になりません。公式ドキュメントのとおり、ハッシュできない既定値はインスタンスごとにディープコピーされるためです。dataclassの感覚で`default_factory=list`と書いても動きますが、必須ではありません。

### 2.10で入った検証済みデータを受け取るdefault\_factoryの書き方

v2.10から、`default_factory`は引数を1つ取る関数も受け付けます。引数には、そのフィールドより前に定義され、検証を通ったフィールドの値が辞書で渡されます。

```
from pydantic import BaseModel, Field


class Member(BaseModel):
    user_name: str
    # 表示名が送られてこなければ、検証済みの user_name から作る
    display_name: str = Field(default_factory=lambda data: data["user_name"].title())


print(Member(user_name="taro yamada").display_name)
# Taro Yamada
```

参照できるのは定義順で前にあるフィールドだけです。`display_name`を`user_name`より上に書くと、辞書にキーが無く`KeyError`になります。複数のフィールドを見比べて値を決める処理や、入力の矛盾を弾く処理は`model_validator`の役割です。既定値を埋めるだけの用途に絞って使います。

## 数値・文字列・リストの制約引数とJSON Schemaへの変換規則

制約引数は入力の検証に使われるだけでなく、JSON Schemaのキーワードにも変換されます。対応を知っておくと、フロントエンドとAPIで同じ条件を共有できます。

### gt・ge・max\_length・patternの対応表と違反時のエラー種別

[v2.14.3のjson\_schema.py](https://github.com/pydantic/pydantic/blob/v2.14.3/pydantic/json%5Fschema.py)にある変換表を、型ごとにまとめると次のとおりです。

| Fieldの引数     | 対象の型      | JSON Schema      |
| ------------ | --------- | ---------------- |
| gt           | int・float | exclusiveMinimum |
| ge           | int・float | minimum          |
| lt           | int・float | exclusiveMaximum |
| le           | int・float | maximum          |
| multiple\_of | int・float | multipleOf       |
| min\_length  | str       | minLength        |
| min\_length  | list      | minItems         |
| max\_length  | dict      | maxProperties    |
| pattern      | str       | pattern          |

同じ`min_length`でも、文字列なら`minLength`、リストなら`minItems`に変わります。先ほどの`OrderLine`で確かめると、次の出力になります。

```
print(OrderLine.model_json_schema()["properties"]["quantity"])
# {'default': 1, 'exclusiveMinimum': 0, 'maximum': 100, 'title': 'Quantity', 'type': 'integer'}
```

違反したときのエラー種別は、`gt`なら`greater_than`、`max_length`（文字列）なら`string_too_long`です。種別で分岐して日本語のメッセージに置き換えると、422の応答を利用者向けに整えられます。JSON Schemaのキーワード自体の意味は[JSON Schemaの書き方とDraft 2020-12の解説](https://www.issoh.co.jp/tech/details/16289/)にまとめています。

### patternで先読みが使えないrust-regexとpython-reの切り替え

`pattern`の正規表現は、既定ではPythonの`re`ではなくRust製のエンジンで評価されます。config.pyの説明では、既定の`rust-regex`はバックトラックをしないためReDoS（正規表現による処理遅延の攻撃）に強い一方、一部の構文を持ちません。代表例が先読みの`(?=...)`です。

```
from pydantic import BaseModel, ConfigDict, Field


class PasswordInput(BaseModel):
    # 先読みを使うため re モジュールに切り替える（v2.5以上）
    model_config = ConfigDict(regex_engine="python-re")

    # 英字と数字を両方含む8文字以上
    value: str = Field(pattern=r"^(?=.*[A-Za-z])(?=.*\d).{8,}$")
```

切り替えはモデル単位です。外部から受け取る文字列に`python-re`を使うと、書き方次第で処理時間が入力長に対して急増するため、先読みが要る1つのモデルだけに限定します。先読みを使わず「英字を含む」「数字を含む」を`field_validator`で2回判定する方が、エンジンを切り替えずに済む分だけ安全です。

## 3種類のaliasでcamelCaseのJSONを受け取り返す実装と注意点

外部APIやフロントエンドがcamelCaseで値をやり取りする一方、Pythonのコードはsnake\_caseで書きたい、という場面で使うのがaliasです。

### 検証用と出力用でaliasを分けるAliasChoicesとAliasPathの書き方

aliasは3種類あります。`alias`は入力と出力の両方、`validation_alias`は入力だけ、`serialization_alias`は出力だけに効きます。fields.pyでは、`alias`だけを指定すると残り2つに同じ値が入る作りです。

```
from pydantic import AliasChoices, AliasPath, BaseModel, Field


class Customer(BaseModel):
    customer_id: int = Field(alias="customerId")
    # 旧APIの "name" と新APIの "fullName" のどちらでも受け取る
    full_name: str = Field(validation_alias=AliasChoices("fullName", "name"))
    # {"address": {"zip": "..."}} の入れ子から取り出す
    zip_code: str = Field(validation_alias=AliasPath("address", "zip"))


c = Customer.model_validate(
    {"customerId": 1, "name": "山田", "address": {"zip": "100-0001"}}
)
print(c.model_dump())
# {'customer_id': 1, 'full_name': '山田', 'zip_code': '100-0001'}
print(c.model_dump(by_alias=True))
# {'customerId': 1, 'full_name': '山田', 'zip_code': '100-0001'}
```

`AliasChoices`は左から順に探し、最初に見つかったキーを使います。APIのキー名を移行する期間に、新旧どちらの名前でも受け付けたいときに適した指定です。aliasを付けると、既定では`Customer(customer_id=1)`のようにフィールド名で値を渡せなくなります。両方を許す`validate_by_name`や、全フィールドをまとめてcamelCaseにする`alias_generator`は[ConfigDictの設定一覧](https://www.issoh.co.jp/tech/details/7583/)で扱っています。

### model\_dumpのby\_alias既定値とFastAPIの応答で名前が変わる仕組み

上の出力のとおり、`model_dump()`は既定（`by_alias=False`）ではフィールド名で出力します。ところがFastAPIの応答では、同じモデルがalias名で返ります。FastAPI 0.162.7のrouting.pyで、パス操作の`response_model_by_alias`の既定が`True`だからです。

この差が原因で、「テストで`model_dump()`した結果とAPIの応答のキー名が違う」という食い違いが起きます。APIの応答と同じ形を得たいテストで使うのは、`model_dump(by_alias=True)`です。モデル全体で既定を変えるなら、ConfigDictの`serialize_by_alias=True`を指定します。

環境変数名を変える用途でも`validation_alias`は使えます。pydantic-settingsで`env_prefix`と組み合わせたときの挙動は[pydantic-settingsの使い方](https://www.issoh.co.jp/tech/details/19769/)で説明しています。

## FastAPIのSwagger UIへFieldの説明と例を反映する書き方

FastAPIでは、リクエストとレスポンスのモデルに書いたFieldの情報が、そのまま`/openapi.json`とSwagger UIに出ます。

### descriptionとexamplesをOpenAPIのスキーマへ載せる手順

```
from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI()


class ItemIn(BaseModel):
    name: str = Field(min_length=1, max_length=50, description="商品名", examples=["USBケーブル"])
    price: int = Field(ge=0, description="税抜価格（円）", examples=[1280])
    legacy_code: str | None = Field(default=None, deprecated="v2 APIで廃止予定。codeを使う")


@app.post("/items")
def create_item(item: ItemIn) -> ItemIn:
    return item
```

起動して`/openapi.json`を開くと、`components.schemas.ItemIn`の各プロパティに`description`、`examples`、`maxLength`などが並び、`legacy_code`には`"deprecated": true`が付きます。[FastAPI公式のリクエスト例の解説](https://fastapi.tiangolo.com/tutorial/schema-extra-example/)によると、FastAPI 0.99.0以降はOpenAPI 3.1.0を出力し、`examples`はJSON Schemaのリストとして入ります。

`description`は人が読むためだけの欄ではありません。LLMに構造化出力をさせる際には、モデルのJSON Schemaが指示として渡り、descriptionが各項目の意味の説明になります。その仕組みは[LLM構造化出力の仕組みと実装](https://www.issoh.co.jp/tech/details/16322/)で解説しています。Swagger UI側の表示の調整は[FastAPIのSwagger UIの使い方](https://www.issoh.co.jp/tech/details/2246/)が詳しいです。

### deprecatedとexclude\_ifで廃止予定の項目と出力を制御する方法

`deprecated`（v2.7.0追加）を付けたフィールドは、JSON Schemaに`deprecated`が付くほか、Pythonのコードから値を読んだときに`DeprecationWarning`が出ます。APIの利用者とアプリの開発者の両方に、廃止予定を1か所の記述で伝えられます。

```
from pydantic import BaseModel, Field


class UserOut(BaseModel):
    name: str
    password_hash: str = Field(exclude=True, repr=False)  # 出力にもログにも出さない
    nickname: str | None = Field(default=None, exclude_if=lambda v: v is None)


print(UserOut(name="taro", password_hash="xxx").model_dump())
# {'name': 'taro'}
```

`exclude=True`は常に出力から外し、`repr=False`は`print`やログの表示から外します。v2.12で加わった`exclude_if`は、値を見て外すかを決める引数です。「Noneのときだけキーごと省く」応答を、`model_dump(exclude_none=True)`を呼ぶ側に頼らずモデルの定義で保証できます。

## v1のFieldからの移行とField()を使わずに済ませる場面の判断

古い記事やv1時代のコードをそのまま貼ると、Fieldの引数でエラーや警告が出ます。最後に移行の対応と、Fieldを書かない判断を整理します。

### regex・min\_items・constなどv1の引数が出すエラーと置き換え先

v2.14.3のfields.pyでは、v1の引数を「エラーで止めるもの」と「警告を出して読み替えるもの」に分けています。

| v1の引数                 | 2.14.3の挙動 | 置き換え先                   |
| --------------------- | --------- | ----------------------- |
| regex                 | エラー       | pattern                 |
| const                 | エラー       | Literal型                |
| unique\_items         | エラー       | set型                    |
| min\_items・max\_items | 警告        | min\_length・max\_length |
| allow\_mutation       | 警告        | frozen                  |
| 上記以外の任意キー             | 警告        | json\_schema\_extra     |

厄介なのは最後の行です。`Field(minimum=0)`のように存在しない引数を渡すと、警告とともに`json_schema_extra`へ入り、スキーマには`minimum`が出ます。それでも入力の検証は一切行われません。警告を見落とすと「仕様書には下限があるのに負の値が通る」状態になるため、移行時は`-W error::DeprecationWarning`を付けてテストを走らせ、警告をエラーとして洗い出します。

### Field()を書かず型ヒントだけで足りる場面と書くべき場面の線引き

すべてのフィールドにFieldを書く必要はありません。社内のバッチが読む設定ファイルのように、入力元が自分たちのコードだけなら、`int`や`str`の型ヒントで十分です。

Fieldを書くべきなのは、次のどれかに当たるフィールドです。優先度が一番高いのは1つ目です。

- 外部から受け取る値で、範囲や長さの上限がある（金額、件数、自由入力の文字列）
- キー名がPythonの命名と異なる（camelCase、旧APIの名前）
- OpenAPIで他チームや取引先に仕様として公開する
- 出力やログに出してはいけない値を含む

自由入力の文字列に`max_length`が無いと、数MBの文字列がそのままDBや外部APIまで届きます。既存のAPIの入力検証を見直し、Pydanticのモデルを仕様の正本にする作り直しは、[API開発・システム連携の受託開発](https://www.issoh.co.jp/service/system/api/)でご相談を受け付けています。

### SQLModelのFieldやFastAPIのQueryと混同しやすい違いと見分け方

名前が似た別物が2つあります。1つは`from sqlmodel import Field`で、`primary_key`や`foreign_key`などテーブル定義の引数を持つSQLModel独自の関数です。Pydanticの`Field`とimport元を取り違えると、`primary_key`が無いというエラーになります。使い方は[SQLModelのモデル定義とFastAPI連携](https://www.issoh.co.jp/tech/details/10322/)を参照してください。

もう1つはFastAPIの`Query`・`Path`・`Body`です。どれもPydanticの`FieldInfo`を継承しているため、`max_length`や`ge`など同じ名前の制約を使えます。ボディのモデルの中ではPydanticの`Field`、関数の引数ではFastAPIの`Query`などと覚えれば迷いません。POSTのボディで422が返ったときの読み方は[FastAPIでPOSTを受け取る方法と422の直し方](https://www.issoh.co.jp/tech/details/19737/)で扱っています。

## よくある質問

Pydantic Fieldについて出てくることの多い質問に、2026年11月時点の版（pydantic 2.14.3、FastAPI 0.162.7）で答えます。

### Fieldとfield\_validatorはどう使い分けますか？

Fieldの制約引数で表せる条件はFieldに書き、表せない条件だけを`field_validator`で書きます。範囲、長さ、正規表現はFieldで足り、JSON Schemaにも出力されます。一方、「全角カナのみ」「祝日を除く日付」のような業務ルールや、値の正規化（前後の空白を除くなど）はバリデータの役割です。バリデータに書いた条件はJSON Schemaに出ないため、API仕様書に載せたい条件はできるだけFieldで表します。

### Fieldで設定した制約をあとから確認する方法はありますか？

2通りあります。`Model.model_fields["quantity"]`で`FieldInfo`を取り出すと、`metadata`に制約、`alias`や`description`に各値が入っています。v2.11から`model_fields`はインスタンスではなくクラスから読む形が推奨で、インスタンス経由は非推奨です。外部に渡すなら`Model.model_json_schema()`でJSON Schemaとして取り出す方が扱いやすいでしょう。

### Annotatedの中にdefaultを書いてもよいですか？

実行時は動作しますが、勧めません。mypyやPyrightなどの型チェッカーは、Annotatedの中のFieldを見ずに`__init__`の引数を判断します。そのため既定値がある項目でも必須と判定され、呼び出し側に誤った警告が出ます。`quantity: Annotated[int, Field(gt=0)] = 1`のように、制約はAnnotatedの中、既定値は代入で書き分けるのが公式ドキュメントの推奨です。

### Field(frozen=True)とConfigDictのfrozenは何が違いますか？

両者の違いは、書き換えを禁止する対象の範囲です。`Field(frozen=True)`はそのフィールドだけを書き換え禁止にし、代入時のエラーは`frozen_field`のValidationErrorです。`ConfigDict(frozen=True)`はモデルのすべてのフィールドを書き換え禁止にし、インスタンスをハッシュ可能にします。IDや作成日時だけを固定し、他は更新させたいモデルなら、フィールド単位の`frozen`を選びます。

### strict=Trueを付けるとどのような入力が弾かれますか？

既定のlaxモードでは、`int`のフィールドに文字列の`"10"`が来ると整数の10に変換して受け付けます。`Field(strict=True)`を付けたフィールドではこの変換をせず、型が違えばエラーにする設定です。ただしJSONを入力にした場合、日付や`UUID`などJSONに専用の型が無い値は、strictでも文字列から変換されます。金額のように取り違えると損害が大きい数値だけに付けるのが現実的です。

## 関連記事

- [Pydanticとは？読み方・BaseModelの使い方とV1との違い【2.14対応】](https://www.issoh.co.jp/tech/details/4838/)：Fieldの土台になるBaseModelの入門です。
- [Pydantic v2のConfigDict設定一覧｜model\_configの書き方とv1からの移行【2.14対応】](https://www.issoh.co.jp/tech/details/7583/)：モデル全体に効く設定の一覧です。
- [pydantic-settingsの使い方：BaseSettingsで.env・環境変数・シークレットを型安全に読む](https://www.issoh.co.jp/tech/details/19769/)：Fieldと同じ書き方で設定を読む方法です。
- [FastAPIでPOSTを受け取る方法｜JSON・Form・ファイル・Requestの使い分けと422の直し方](https://www.issoh.co.jp/tech/details/19737/)：制約違反で返る422の読み方です。
- [JSON Schemaとは？JSONの構造を検証する書き方とDraft 2020-12の実装を実装者目線で解説【2026年版】](https://www.issoh.co.jp/tech/details/16289/)：Fieldから出力されるスキーマの仕様です。

---

出典: [Pydantic Fieldの使い方：default\_factory・alias・制約の引数一覧とOpenAPIへの反映【2.14対応】](<https://www.issoh.co.jp/tech/details/19771/>)（株式会社一創）
