pydantic模型结构很大程度相似的对象?

发布于 2025-01-29 06:22:32 字数 1549 浏览 0 评论 0原文

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

我与(JSON)合作的数据集在整个过程中大多是相同的结构,但是有些差异仅在树的最低水平下降低。 IE:

// 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模型的建议方法(在这种情况下,它将具有“名称”和“数据”),然后更改在逐案?

我有一个工作的例子,但是感觉很冗长吗?

工作示例:

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")

以上可以工作,但是感觉就像每次(具有“名称”和“数据”的零件)构建项目“持有人”是多余的吗?是否可以指定通用的“容器”结构,然后交换“数据”“?类似:

class GenericContainer(BaseModel):
    Name: str
    Data: ????

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

或类似的东西?在这种情况下,我有几打这些唯一的“项目”(仅在其它们的'中'数据零件)似乎不正确地为每个类别创建两个类别吗

?数据,但在这种情况下是理想的,这是一个理想的选择

I wonder if anyone might have a suggestion for a better way to build up a Pydantic model for this case?

The data set I am working with (JSON) is mostly the same structure throughout, but with some differences only down at the lowest levels of the tree. ie:

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

So I am wondering, is there a suggested method for building a Pydantic model that uses a standard 'Item' (in this case, it would have 'Name' and 'Data'), but then change the 'Data' on a case-by-case basis?

I have a working example, but it feels quite verbose?

working example:

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")

The above does work, but it feels like building the Item 'holder' each time (the part with 'Name' and 'Data') is redundant? Is there way to specify a generic 'container' structure, and then swap out the 'Data'"? Something like:

class GenericContainer(BaseModel):
    Name: str
    Data: ????

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

or something of that sort? In this case I have several dozen of these unique 'Items' (only unique in their 'Data' part) and it doesn't seem correct to create 2 classes for each one? Does it?

I do realize that using the type Dict in place of the detailed 'Data' does work to load in the data, but it comes in as a dict instead of an object, which is not ideal in this case.

any thoughts or suggestions are much appreciated. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧伤还要旧人安 2025-02-05 06:22:32

根据HernánAlarcó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"}}})

所以它有效,
但是我不确定我会选择通用性与可读性。

Based on the comment from Hernán Alarcón, i wanted to try and
i believe this should work. Perhaps it will usefull to someone.

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"}}})

So it works,
but i am not sure i'd choose genericity versus readability.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文