ヒトリ歩き

愚痴とかいろいろ書きます

pydanticのRootModelの恩恵って何?

pydanticのRootModelは何に使うのか?

pydanticのRootModelはListやDictの値に対してpydanticの恩恵を受けたいときに使うらしい。

pydanticを使い出したときに、ListやDictを使う時はRootModelが必要と教えてもらったので、素直にRootModelを使っていたけど、なぜRootModelを使う必要があるのかを理解していなかった。
ListをもつデータをデシリアライズするときにRootModelを使わないとデシリアライズが出来ないってこと??

というこで、以下のソースで試してた。

from pydantic import BaseModel, RootModel
from typing import List

class Product(BaseModel):
    id: int
    name: str = None
    cost: int

class Store(BaseModel):
    products: List[Product]

data = {
    "products": [
        {
            "id": 1,
            "name": "poteto",
            "cost": 100
        },
        {
            "id": 2,
            "cost": 500
        }
    ]
}

store = Store.model_validate(data)
print(store.model_dump(exclude_none=True))

model_dump関数にexclude_noneをTrueにしてもNoneのデータが返ってくるのかなと思ったけど、そういうわけではないみたい。
RootModelの値をループで処理したい際に、store.products.rootで参照する必要があるが、__iter__関数を定義すれば、store.productsで参照できる。 また、保持している要素数を取得する場合、__len__関数を実装する必要がある。

from pydantic import BaseModel, RootModel
from typing import List

class Product(BaseModel):
    id: int
    name: str = None
    cost: int = 0

class Products(RootModel):
    root: List[Product]

    def __iter__(self):
        return iter(self.root)

class Store(BaseModel):
    products: Products

data = {
    "products": [
        {
            "id": 1,
            "name": "poteto",
            "cost": 100
        },
        {
            "id": 2,
            "name": "beaf",
            "cost": 500
        }
    ]
}

store = Store.model_validate(data)

for product in store.products:
    print("name = " + str(product.name))

最後に

個人的にはRootModelを使うメリットをあまり感じることが出来なかった。
もう少しドキュメントを読んで、理解した方がいいかと思う。 ただ、RootModelを使わないくてもいいという理由もないので、素直にRootModelを使用するのが無難だなと思った。
RootModelを使う場合、要素数を取得するときやループで使う場合、抽象メソッドの実装を忘れずに。(.rootで参照するのはダサいし、保守する人も何これ?ってなる)

docs.python.org

参考

docs.pydantic.dev

shotanukumizu-1000.hatenablog.com