Skip to content

Instantly share code, notes, and snippets.

@masakielastic
Last active November 30, 2025 20:44
Show Gist options
  • Select an option

  • Save masakielastic/d2c81b137c78e9ae985d700ac8ebb064 to your computer and use it in GitHub Desktop.

Select an option

Save masakielastic/d2c81b137c78e9ae985d700ac8ebb064 to your computer and use it in GitHub Desktop.

REPL で Pydantic を学ぶ

Pyndantic v2 を前提とします。

パッケージの導入

仮想環境を作成します。

uv venv --python 3.13
source .venv/bin/activate

pip コマンドでインストールします。

uv pip install pydantic

REPL を起動させます。

python

データクラスの作成

モジュールおよびデータクラスを作成します。

from pydantic import BaseModel

class User(BaseModel):
    id: int
    name: str

u = User(id=1, name="Alice")

まずはデータクラスの中身を調べてみましょう。e

u
User(id=1, name='Alice')

バリデーション

別のデータクラスを作成してみましょう。id に文字列としての数字を投入します。

User(id="1", name="Bob")

結果は自動的に数値に変換されます。

User(id=1, name='Bob')

今度は id に数字ではない文字列を投入します。

User(id="abc", name="Carol")
Traceback (most recent call last):
  File "<python-input-5>", line 1, in <module>
    User(id="abc", name="Carol")
    ~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/masakielastic/pydantic-project/.venv/lib/python3.13/site-packages/pydantic/main.py", line 250, in __init__
    validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
pydantic_core._pydantic_core.ValidationError: 1 validation error for User
id
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='abc', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/int_parsing

model_dumpmodel_dump_json

u = User(id=1, name="Alice")
u.model_dump()
{'id': 1, 'name': 'Alice'}
u.model_dump_json()
'{"id":1,"name":"Alice"}'

デフォルトと Optional

from typing import Optional

class Item(BaseModel):
    title: str
    price: float = 0.0
    memo: Optional[str] = None
Item(title="Book")
Item(title='Book', price=0.0, memo=None)

型注釈

class Point(BaseModel):
    x: float
    y: float
points = [Point(x=i, y=i**2) for i in range(5)]
points
[Point(x=0.0, y=0.0), Point(x=1.0, y=1.0), Point(x=2.0, y=4.0), Point(x=3.0, y=9.0), Point(x=4.0, y=16.0)]

入れ子クラス

class Address(BaseModel):
    city: str

class Person(BaseModel):
    name: str
    address: Address
p = Person(name="Alice", address={"city": "Tokyo"})
p

フィールドバリデーター

from pydantic import BaseModel, field_validator

class Product(BaseModel):
    name: str
    price: float

    @field_validator("price")
    def check_price(cls, v):
        if v < 0:
            raise ValueError("negative!")
        return v

正の値を投入してみます。

Product(name="Tea", price=200)

負の値を投入するとエラーになります。

Product(name="Tea", price=-100)
Traceback (most recent call last):
  File "<python-input-21>", line 1, in <module>
    Product(name="Tea", price=-199)
    ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/masakielastic/pydantic-project/.venv/lib/python3.13/site-packages/pydantic/main.py", line 250, in __init__
    validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
pydantic_core._pydantic_core.ValidationError: 1 validation error for Product
price
  Value error, negative! [type=value_error, input_value=-199, input_type=int]
    For further information visit https://errors.pydantic.dev/2.12/v/value_error

JSON の読み込み

from pydantic import BaseModel

class User(BaseModel):
    id: int
    name: str

json_str = '{"id": 1, "name": "Alice"}'
json_str = '{"id": 1, "name": "Alice"}'
u = User.model_validate_json(json_str)

u の中身を見ています。

u

型を調べてみます。

type(u))
<class '__main__.User'>

JSON を辞書に変換してからデータクラスに投入する方法を試してみます。

import json
from pydantic import BaseModel

class User(BaseModel):
    id: int
    name: str

json_str = '{"id": "1", "name": "Bob"}'
data = json.loads(json_str)
u = User.model_validate(data)
u

不正な値が投入された場合をチェックしてみます。

from pydantic import BaseModel, ValidationError

class User(BaseModel):
    id: int
    name: str

try:
    User.model_validate_json('{"id": "abc", "name": "Alice"}')
except ValidationError as e:
    print(e)

結果です。

1 validation error for User
id
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='abc', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/int_parsing

JSON スキーマを生成する

from pydantic import BaseModel

class User(BaseModel):
    id: int
    name: str
schema = User.model_json_schema()
schema

出力例

{
    'title': 'User',
    'type': 'object',
    'properties': {
        'id': {'title': 'Id', 'type': 'integer'},
        'name': {'title': 'Name', 'type': 'string'}
    },
    'required': ['id', 'name']
}

JSON として保存するには json_dump を使います。

schema_json = json.dumps(schema, indent=2)
schema_json

'{\n "properties": {\n "id": {\n "title": "Id",\n "type": "integer"\n },\n "name": {\n "title": "Name",\n "type": "string"\n }\n },\n "required": [\n "id",\n "name"\n ],\n "title": "User",\n "type": "object"\n}'


JSON スキーマをファイルに保存する。

import json

with open("schema.json", "w") as f: json.dump(User.model_json_schema(), f, indent=2)


例外
----


```python
from pydantic import BaseModel, ValidationError

class User(BaseModel):
    id: int
    name: str

try:
    User.model_validate({"id": "abc", "name": "Alice"})
except ValidationError as e:
    print("ERROR:", e)

結果のエラーです。

ERROR: 1 validation error for User
id
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='abc', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/int_parsing

JSON 形式でエラーを出力させることもできます。

try:
    User.model_validate({"id": "abc", "name": "Alice"})
except ValidationError as e:
    print(e.errors())

strict モード

デフォルトモードでは型変換が行われます。

class User(BaseModel):
    id: int
    name: str

u = User.model_validate({"id": "1", "name": 123})
print(u)
print(type(u.id), type(u.name))

strict モードでは型変換が認められません。

from pydantic import BaseModel, StrictInt, StrictStr

class User(BaseModel):
    id: StrictInt
    name: StrictStr

User.model_validate({"id": "1", "name": 123})
pydantic_core._pydantic_core.ValidationError: 2 validation errors for User
id
  Input should be a valid integer [type=int_type, input_value='1', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/int_type
name
  Input should be a valid string [type=string_type, input_value=123, input_type=int]
    For further information visit https://errors.pydantic.dev/2.12/v/string_type

モデル全体を strict モードにしてみます。

from pydantic import BaseModel

class User(BaseModel):
    id: int
    name: str

    model_config = {
        "strict": True
    }

試してみます。

User.model_validate({"id": "1", "name": "Alice"})

pytest

uv pip install pytest
import pytest
from pydantic import BaseModel, ValidationError

class User(BaseModel):
    id: int

def test_valid():
    u = User.model_validate({"id": 1})
    assert u.id == 1

def test_invalid():
    with pytest.raises(ValidationError):
        User.model_validate({"id": "abc"})
python -m pytest
==================================================== test session starts =====================================================
platform linux -- Python 3.13.9, pytest-9.0.1, pluggy-1.6.0
rootdir: /home/masakielastic/pydantic-project
collected 2 items                                                                                                            

test_validation.py ..                                                                                                  [100%]

===================================================== 2 passed in 0.07s ======================================================
(pydantic-project) masakielastic@penguin:~/pydantic-project$ ls
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment