try 使用PYDANIC对json文件建模,如下所示:

{
    "people": {
        "Jack": {"age": 32, "postcode": 1223},
        "Robert": {"age": 23, "postcode":2354},
        "Sarah": {"age": 55, "postcode":5673}
    }
}

我还有一个我喜欢强制执行的可接受名称的列表:

accepted_names = ["Jack", "Robert", "Sarah", "Alex"]

我曾try 使用__root__:[Dict[str, Dict[str, int]],但在版本2中不建议使用,错误消息说我应该使用RootModel,但pydatics文档并不清楚如何做到这一点.

到目前为止,我所拥有的是:

import json 
from pydantic import BaseModel, RootModel, conint
from typing import Dict

class PersonModel(BaseModel):
    age: conint(ge=0)
    postcode: conint(ge=1000, le=9999)

class MyModel(RootModel):
    root:Dict[str, PersonModel]

    def validate_root(cls, v):
       acceptable_names =  ["Jack", "Robert", "Sarah", "Alex"]
       if v not in acceptable_names:
            raise ValueError(f"Names should be one of {', '.join(acceptable_names)}")
       return v
        
class ParentModel(BaseModel):
     people: MyModel

file = "scratch/test.json"
with open(file, "r") as f:
        data = json.load(f)

mymodel = ParentModel(**data)

但它现在的工作方式是mymodel.people.root['Jack'],而我想要mymodel.people.Jack

推荐答案

我的回答

我认为您可以修改RootModel的方法__getattr__,而不是调用.root.

    def __getattr__(self, item: str):
        return self.root.__getitem__(item)

我的例子

from pydantic import BaseModel, RootModel, conint, ConfigDict
from typing import Dict


data = {
    "people": {
        "Jack": {"age": 32, "postcode": 1223},
        "Robert": {"age": 23, "postcode": 2354},
        "Sarah": {"age": 55, "postcode": 5673},
    }
}

class PersonModel(BaseModel):
    age: conint(ge=0)
    postcode: conint(ge=1000, le=9999)

class ParentModel(BaseModel):
    class MyModel(RootModel[Dict[str, PersonModel]]):
        def __getattr__(self, item: str):
            return self.root.__getitem__(item)

    people: MyModel


mymodel = ParentModel.model_validate(data)
print(mymodel.people)
# > root={'Jack': PersonModel(age=32, postcode=1223), 'Robert': PersonModel(age=23, postcode=2354), 'Sarah': PersonModel(age=55, postcode=5673)}
print(mymodel.people.Jack)
# > age=32 postcode=1223

Python相关问答推荐

如何在Python中使用ijson解析SON期间检索文件位置?

如何修复使用turtle和tkinter制作的绘画应用程序的撤销功能

基本链合同的地址是如何计算的?

如何使用上下文管理器创建类的实例?

使用from_pandas将GeDataFrame转换为polars失败,ArrowType错误:未传递numpy. dype对象

删除最后一个pip安装的包

处理(潜在)不断增长的任务队列的并行/并行方法

更改键盘按钮进入'

如何在Python中并行化以下搜索?

我们可以为Flask模型中的id字段主键设置默认uuid吗

Odoo 16使用NTFS使字段只读

如何在UserSerializer中添加显式字段?

Scrapy和Great Expectations(great_expectations)—不合作

转换为浮点,pandas字符串列,混合千和十进制分隔符

Django—cte给出:QuerySet对象没有属性with_cte''''

为什么我的sundaram筛这么低效

如何使用正则表达式修改toml文件中指定字段中的参数值

在Python中控制列表中的数据步长

当我定义一个继承的类时,我可以避免使用`metaclass=`吗?

从列表中分离数据的最佳方式