guest@blog.cmj.tw: ~/posts $

Pydantic


主要是介紹使用 Pydantic (v2) 的各種方式。

Example 1

基本上來說,可以使用 BaseModel 來簡單定義一個 schema。 之後就可以透過 type hinting 來定義資料的型態,並且在建立的時候做檢查:

from pydantic import BaseModel


class Example(BaseModel):
    name: str
    age: int


data = Example(name="Alice", age=20)
print(data.model_dump())  # {'name': 'Alice', 'age': 20}

Example 2 - with default value

在某些情況下,你希望這個資料結構有預設的值,可以這樣做:

  1. 直接使用 = 來設定預設值
  2. 使用 Field 來設定預設值
from pydantic import BaseModel
from pydantic import Field


class Example(BaseModel):
    name: str
    age: int = 18
    country: str = Field(default="Taiwan")


data = Example(name="Alice")  # {'name': 'Alice', 'age': 18, 'country': 'Taiwan'}

Example 3 - with Polymorphic

有時候,你會希望這個資料結構可以是多種型態或想要資料可以留空,就可以使用這些方式:

  1. 使用 typing.Union 來定義多種型態
  2. 直接使用 | 來定義多種型態
from pydantic import BaseModel
from typing import Union


class Example(BaseModel):
    name: str
    age: int | str
    country: Union[str, None]

data1 = Example(name="Alice", age=20, country="Taiwan")
data2 = Example(name="Bob", age="unknown", country=None)


print(data1.model_dump())  # {'name': 'Alice', 'age': 20, 'country': 'Taiwan'}
print(data2.model_dump())  # {'name': 'Bob', 'age': 'unknown', 'country': None}

Example 4 - as List or Dict

有時候你會希望這個資料結構是一個 list,可以使用 RootModel 來定義:

from pydantic import RootModel


Pets = RootModel[list[str]]

data = Pets(["dog", "cat", "rabbit"])
print(data.model_dump())  # ['dog', 'cat', 'rabbit']

或者是一個 dict:

from pydantic import RootModel


User = RootModel[dict[str, str]]

data = User({"name": "Alice", "age": "20"})
print(data.model_dump())  # {'name': 'Alice', 'age': '20'}

Example 5 - with nested schema

當問題變複雜的時候,你可以重複利用 schema 來定義複雜的資料結構:

from pydantic import BaseModel
from pydantic import RootModel


class Address(BaseModel):
    city: str
    street: str


class User(BaseModel):
    name: str
    age: int
    address: Address


data = User(name="Alice", age=20, address={"city": "Taipei", "street": "Xinyi"})
print(data.model_dump())  # {'name': 'Alice', 'age': 20, 'address': {'city': 'Taipei', 'street': 'Xinyi'}}