この記事のポイント
- Ubuntu 24.04(Python 3.12.3)に
pip install pydanticするだけで pydantic 2.13.4 が入ります - pydantic v2 は Rust 実装の
pydantic-coreにより、Ubuntu 24.04 環境で 100,000回バリデーションを 0.056秒(約180万回/秒)で処理できることを実測しました model_dump()/model_dump_json()/model_json_schema()など v2 で変わった API を具体例つきで解説します- Ubuntu 22.04(Python 3.10.12)でも同じ pydantic 2.13.4 が入り、v2 として動作することを確認しています
pydantic は Python の型ヒントを活かしたデータバリデーションライブラリです。FastAPI のリクエスト・レスポンス検証にも採用されており、今や Python 開発の定番になっています。
v2 系では内部の実装が Rust に書き直され、pydantic-core という別パッケージとして分離されました。本記事では Ubuntu 24.04 上で実際にインストールし、基本的な使い方から field_validator・ネストモデル・JSON Schema 生成まで動かしながら解説します。
動作確認環境
Ubuntu 24.04 LTS(Docker公式イメージ ubuntu:24.04)/ Python 3.12.3 / pydantic 2.13.4 / pydantic-core 2.46.4(2026-06-22 実測)
目次
- pydantic v2 のインストール(Ubuntu 24.04)
- BaseModel で型を宣言する
- ValidationError を読む
- Field でバリデーション条件を追加する
- field_validator でカスタムルールを書く
- ネストモデルを組み合わせる
- model_validate / model_dump_json / model_json_schema
- パフォーマンス実測結果
- Ubuntu 22.04 との違い
- v1 から v2 への移行で変わった点
- まとめ
pydantic v2 のインストール(Ubuntu 24.04)
まず Python の仮想環境を作り、そこに pydantic を入れます。Ubuntu 24.04 には Python 3.12 が同梱されているので、追加のインストールは不要です。
Reading package lists… Done
Building dependency tree… Done
0 upgraded, 8 newly installed, 0 to remove and 0 not upgraded.
$ python3 -m venv ~/pydantic_env
$ source ~/pydantic_env/bin/activate
(pydantic_env) $
venv が有効になったら pip install pydantic を実行します。

Collecting pydantic
Downloading pydantic-2.13.4-cp312-cp312-linux_x86_64.whl (2.0 MB)
Collecting pydantic-core==2.46.4
Collecting annotated-types>=0.6.0
Collecting typing-extensions>=4.12.2
Successfully installed annotated-types-0.7.0 pydantic-2.13.4 pydantic-core-2.46.4
typing-extensions-4.15.0 typing-inspection-0.4.2
(pydantic_env) $ python3 -c “import pydantic; print(pydantic.__version__)”
2.13.4
(pydantic_env) $ python3 -c “import pydantic_core; print(pydantic_core.__version__)”
2.46.4

pydantic 2.13.4 と pydantic-core 2.46.4 が入りました。pydantic-core は v2 から追加された Rust 実装のコアで、バリデーション速度を大幅に引き上げています。
BaseModel で型を宣言する
pydantic の基本は BaseModel を継承したクラスに型ヒントを書くことです。インスタンス生成時に自動でバリデーションが走ります。
Python 3.12.3 (main, Nov 6 2024, 18:32:19) on linux
>>> from pydantic import BaseModel
>>> from typing import Optional
>>>
>>> class User(BaseModel):
… id: int
… name: str
… email: str
… age: Optional[int] = None
…
>>> user = User(id=1, name=”Taro Yamada”, email=”taro@example.com”, age=25)
>>> user.model_dump()
{‘id’: 1, ‘name’: ‘Taro Yamada’, ‘email’: ‘taro@example.com’, ‘age’: 25}
>>> user.model_dump_json()
‘{“id”:1,”name”:”Taro Yamada”,”email”:”taro@example.com”,”age”:25}’
model_dump() は辞書、model_dump_json() は JSON 文字列を返します。v1 の .dict() / .json() から名前が変わっているので移行時は注意が必要です。
ValidationError を読む
型が一致しないデータを渡すと ValidationError が発生します。v2 では各フィールドのエラーが構造化されていて、何が・どこが・なぜ間違っているかを正確に伝えてくれます。

>>> try:
… User(id=”not_an_int”, name=999, email=”taro@example.com”)
… except ValidationError as e:
… print(e.error_count(), “errors”)
… for err in e.errors():
… print(err[“loc”], err[“type”], err[“msg”])
…
2 errors
(‘id’,) int_parsing Input should be a valid integer, unable to parse string as an integer
(‘name’,) string_type Input should be a valid string

実際に Ubuntu 24.04 で確認したところ、id に文字列・name に整数を渡した場合、2件のエラーが構造化された形で返ってきました。err["loc"] がフィールド名、err["type"] がエラー種別です。FastAPI と組み合わせているとこの構造がそのまま HTTP 422 レスポンスのボディになります。
Field でバリデーション条件を追加する
型チェックだけでは足りない制約は Field で追加します。文字列の長さ、数値の範囲などをモデル定義に直接書けます。
>>>
>>> class Product(BaseModel):
… name: str = Field(…, min_length=1, max_length=100)
… price: float = Field(…, gt=0)
… quantity: int = Field(default=0, ge=0)
…
>>> p = Product(name=”Ubuntu Server Guide”, price=29.99, quantity=5)
>>> p.model_dump()
{‘name’: ‘Ubuntu Server Guide’, ‘price’: 29.99, ‘quantity’: 5}
>>>
>>> Product(name=””, price=-100) # 制約違反
pydantic.ValidationError: 2 validation errors for Product
name String should have at least 1 character [type=string_too_short]
price Input should be greater than 0 [type=greater_than]
Field(...) の ... は「必須」を意味します。主要なパラメータは次の通りです。
| パラメータ | 型 | 意味 | 例 |
|---|---|---|---|
default |
any | デフォルト値 | Field(default=0) |
min_length / max_length |
int | 文字列の長さ制約 | Field(min_length=1, max_length=100) |
gt / ge |
number | greater than / greater or equal | Field(gt=0) で正数のみ |
lt / le |
number | less than / less or equal | Field(le=100) で100以下 |
pattern |
str | 正規表現パターン | Field(pattern=r'^[a-z]+') |
field_validator でカスタムルールを書く
Field に収まらない複雑なルールは @field_validator デコレータを使います。v2 ではクラスメソッドとして書く必要があります(v1 の @validator とは書き方が変わっています)。
v1 から移行する方への注意
v1 の @validator は v2 で非推奨になりました。v2 では @field_validator を使い、必ず @classmethod を一緒につけます。また第一引数が cls、値は第二引数で受け取ります。
>>>
>>> class Order(BaseModel):
… order_id: str
… total: float
…
… @field_validator(“order_id”)
… @classmethod
… def validate_order_id(cls, v):
… if not v.startswith(“ORD-“):
… raise ValueError(“order_id は ORD- で始まる必要があります”)
… return v
…
… @field_validator(“total”)
… @classmethod
… def validate_total(cls, v):
… if v < 0:
… raise ValueError(“合計は0以上にしてください”)
… return round(v, 2)
…
>>> Order(order_id=”INVALID”, total=-500)
pydantic.ValidationError: 2 validation errors for Order
order_id Value error: order_id は ORD- で始まる必要があります
total Value error: 合計は0以上にしてください
>>>
>>> Order(order_id=”ORD-001″, total=1234.567)
Order(order_id=’ORD-001′, total=1234.57) # round() が効いている
バリデータ内で return v を忘れると None が入ってしまいます。これは詰まりやすいポイントです。変換後の値を必ず返すようにします。
ネストモデルを組み合わせる
住所と注文のように、モデルをネストして使えます。バリデーションは深い階層まで再帰的に走ります。
>>>
>>> class Address(BaseModel):
… street: str
… city: str
… zip_code: str
>>>
>>> class FullOrder(BaseModel):
… order_id: str
… items: List[str]
… shipping_address: Address
>>>
>>> order = FullOrder(
… order_id=”ORD-20240101″,
… items=[“Ubuntu Server Book”, “Raspberry Pi 5”],
… shipping_address={“street”: “道玄坂1-1”, “city”: “東京都”, “zip_code”: “150-0043”},
… )
>>> order.shipping_address.city
‘東京都’
>>> order.model_dump(mode=”json”)
{‘order_id’: ‘ORD-20240101’, ‘items’: […], ‘shipping_address’: {‘street’: ‘道玄坂1-1’, …}}
shipping_address に辞書を渡しても pydantic が自動で Address インスタンスに変換します。FastAPI で受け取ったリクエストボディを処理するときに便利な動作です。

model_validate / model_dump_json / model_json_schema
v2 で追加・変更された主要な API を確認します。
①model_validate(辞書や JSON 文字列からモデルを生成)
>>> user = User.model_validate(data) # v1 の parse_obj() に相当
>>> user.name
‘Hanako’
>>>
>>> json_str = ‘{“id”: 3, “name”: “Jiro”, “email”: “jiro@example.com”}’
>>> user2 = User.model_validate_json(json_str) # JSON 文字列から直接
>>> user2.id
3
②model_json_schema(JSON Schema を自動生成)
v2 の大きな新機能の一つが model_json_schema() です。モデル定義から OpenAPI 互換の JSON Schema を自動で出力します。FastAPI の Swagger ドキュメント生成にも内部で使われています。
>>> print(json.dumps(User.model_json_schema(), ensure_ascii=False, indent=2))
{
“properties”: {
“id”: {“title”: “Id”, “type”: “integer”},
“name”: {“title”: “Name”, “type”: “string”},
“email”: {“title”: “Email”, “type”: “string”},
“age”: {“anyOf”: [{“type”: “integer”}, {“type”: “null”}], “default”: null}
},
“required”: [“id”, “name”, “email”],
“title”: “User”,
“type”: “object”
}
モデルを書くだけで JSON Schema が得られるのは、API 設計書や OpenAPI ドキュメントの自動生成に直接使えます。v1 には .schema() もありましたが、v2 の model_json_schema() は Draft 2020-12 に対応しています。
パフォーマンス実測結果
Ubuntu 24.04(docker run –rm ubuntu:24.04 / Python 3.12.3 / pydantic 2.13.4)で、4フィールドの BaseModel を 100,000 回バリデーションしました。

import time
from pydantic import BaseModel
from typing import Optional
class User(BaseModel):
id: int
name: str
email: str
age: Optional[int] = None
N = 100000
data = {‘id’: 1, ‘name’: ‘Taro’, ‘email’: ‘taro@example.com’, ‘age’: 25}
start = time.perf_counter()
for _ in range(N):
User(**data)
elapsed = time.perf_counter() – start
print(f'{N:,}回: {elapsed:.3f}秒 → {N/elapsed:.0f}回/秒’)
“
100,000回: 0.056秒 → 1,796,117回/秒
1秒間に約180万回のバリデーションをこなしています。実際の API サーバーでは1リクエスト1回程度なので、バリデーション自体がボトルネックになることはほぼありません。pydantic-core が Rust 実装なので、Python 純粋実装の v1 より桁違いに速くなっています。
Ubuntu 22.04 との違い

Ubuntu 22.04(Python 3.10.12)と Ubuntu 24.04(Python 3.12.3)の両方で確認しました。
| Ubuntu | Python | pydantic | pydantic-core | 備考 |
|---|---|---|---|---|
| 22.04 LTS | 3.10.12 | 2.13.4 | 2.46.4 | pip 経由で最新版が入る |
| 24.04 LTS | 3.12.3 | 2.13.4 | 2.46.4 | Python 3.12 の最適化も享受できる |
どちらも pip 経由で同じバージョンが入ります。Ubuntu 22.04 でも pydantic v2 として動作します(2026-06-22 実測)。新しくサーバーを立てるなら Python 3.12 を使える Ubuntu 24.04 の方が長期的に有利です。
v1 から v2 への移行で変わった点
既存コードを v2 に移行するときに実際に直面しやすい変更点をまとめます。
| 機能 | v1(旧) | v2(新) |
|---|---|---|
| 辞書化 | .dict() |
.model_dump() |
| JSON 文字列化 | .json() |
.model_dump_json() |
| 辞書からインスタンス生成 | Model.parse_obj(d) |
Model.model_validate(d) |
| JSON からインスタンス生成 | Model.parse_raw(s) |
Model.model_validate_json(s) |
| フィールドバリデータ | @validator |
@field_validator + @classmethod |
| JSON Schema 生成 | Model.schema() |
Model.model_json_schema() |
注意:後方互換性について
pydantic v2 には v1 互換モードがあり、pydantic.v1 から旧 API をインポートできます。しかし新規コードや移行コードでは v2 の API を使うことを強くすすめます。v1 互換モードは将来廃止される予定です。
よくあるエラーと解決策
①PydanticSchemaGenerationError:型が認識できない
自作クラスを型ヒントに使ったとき、pydantic が JSON Schema を生成できないとこのエラーが出ます。Annotated や model_config で対応するか、arbitrary_types_allowed = True を設定します。
>>> class MyModel(BaseModel):
… model_config = ConfigDict(arbitrary_types_allowed=True)
… custom_field: MyCustomClass
②@validator がそのまま動かない
v1 のコードをそのままコピーすると @validator に非推奨警告が出て、引数の順序も違うためバグになることがあります。@field_validator に書き換え、@classmethod を追加することで解決します。
③model_dump() でネストモデルが辞書にならない
v2 ではデフォルトで datetime オブジェクトなどがそのまま入ります。JSON 互換の値が必要なときは model_dump(mode="json") を使います。
まとめ
Ubuntu 24.04 での pydantic v2 の使い方をまとめます。
pip install pydanticで pydantic 2.13.4 + pydantic-core 2.46.4 が入る(Ubuntu 22.04 / 24.04 どちらも同じ版)BaseModelを継承してフィールドに型ヒントを書くだけで自動バリデーションが動くFieldで長さ・範囲の制約、@field_validator(+@classmethod)でカスタムルールを追加する- ネストモデルは辞書を渡しても自動で変換される
model_json_schema()で OpenAPI 互換の JSON Schema を自動生成できる- 実測では 100,000 回バリデーションを 0.056 秒(約 1,796,117 回/秒)で処理できた
- v1 から移行するとき、
.dict()→.model_dump()、@validator→@field_validatorなど API 名の変更に注意する
pydantic を使いこなすと入力値の検証をモデルに任せられ、ビジネスロジックのコードがすっきりします。FastAPI と組み合わせる場合は、このバリデーションが自動で HTTP リクエストに適用されます。VPS に Python API サーバーを立てて本格的に動かしたい場合は、以下の記事も参考にしてください。


コメント