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で参照するのはダサいし、保守する人も何これ?ってなる)