大致相似的对象的Pydantic模型结构?



我想知道是否有人可能有一个更好的方法来建立Pydantic模型为这种情况的建议?

我正在使用的数据集(JSON)基本上是相同的结构,但只有在树的最低级别上有一些差异。即:

// data.json
{
"FirstItem": {
"Name": "first item",
"Data": {
"attr_1": "a",
"attr_2": "b"
}
},
"SecondItem": {
"Name": "second item",
"Data": {
"attr_3": "d",
"attr_4": "e"
}
},
...
}

所以我想知道,是否有一种建议的方法来构建一个Pydantic模型,使用一个标准的"项目"(在这种情况下,它将有"名称"one_answers"数据"),但然后改变"数据"逐案的基础?

我有一个工作的例子,但是感觉很啰嗦?

工作的例子:

from pydantic import BaseModel
class FirstItemData(BaseModel):
attr_1: str
attr_2: str
class FirstItem(BaseModel):
Name: str
Data: FirstItemData # <--- The unique part
class SecondItemData(BaseModel):
attr_3: str
attr_4: str
class SecondItem(BaseModel):
Name: str
Data: SecondItemData
class Example(BaseModel):
FirstItem: FirstItem
SecondItem: SecondItem
o = Example.parse_file("data.json")

上面的确实可以工作,但是感觉每次构建Item 'holder'(带有'Name'和'Data'的部分)是多余的?是否有办法指定一个通用的"容器"结构,然后换出"数据"?比如:

class GenericContainer(BaseModel):
Name: str
Data: ????
class Example(BaseModel):
FirstItem: GenericContainer(Data = FirstItemData)
SecondItem: GenericContainer(Data = SecondItemData)

之类的?在这种情况下,我有几十个这些独特的"项目"(只有他们的"数据"部分是唯一的),它似乎不正确,为每个创建2个类?不是吗?

我确实意识到使用类型Dict代替详细的'Data'确实可以加载数据,但它是作为字典而不是对象进入的,在这种情况下这是不理想的。

任何想法或建议都非常感谢。谢谢!

根据Hernán Alarcón的评论,我想尝试和我相信这应该行得通。也许它会对某人有用。

from pydantic.generics import BaseModel, GenericModel
from typing import Generic, TypeVar, Optional
class FirstItemData(BaseModel):
attr_1: str
attr_2: str
class SecondItemData(BaseModel):
attr_3: str
attr_4: str
TypeX = TypeVar('TypeX')
class GenericContainer(GenericModel, Generic[TypeX]):
Name: str
Data: TypeX
class ItemBag(BaseModel):
FirstItem: Optional[GenericContainer[FirstItemData]]
SecondItem: Optional[GenericContainer[SecondItemData]]
# some tests
one_bag = ItemBag(FirstItem = {"Name":"My first item", "Data":{"attr_1":"test1", "attr_2":"test2"}})
another_bag = ItemBag(FirstItem = {"Name":"My first item", "Data":{"attr_1":"test1", "attr_2":"test2"}}, SecondItem = {"Name":"My first item", "Data":{"attr_3":"test3", "attr_4":"test4"}})
# failing tests to slightly check validation
one_failing_bag = ItemBag(FirstItem = {"Name":"My first item", "Data":{"attr_3":"test1", "attr_42":"test2"}})
another_failing_bag = ItemBag(SecondItem = {"Name":"My second item", "Data":{"attr_3":"test3", "attr_42":"test2"}})
# the parsing way
parsed_bag = ItemBag.parse_obj({"FirstItem":{"Name":"My first item", "Data":{"attr_1":"test1", "attr_2":"test2"}}, "SecondItem": {"Name":"My first item", "Data":{"attr_3":"test3", "attr_4":"test4"}}})

所以行得通,但我不确定我会选择通用性还是可读性。

最新更新