简体   繁体   English

如何使用 Pydantic 验证复杂的嵌套数据结构?

[英]How to validate a complex nested data structure with Pydantic?

I had complex and nested data structure like below:我有如下复杂且嵌套的数据结构:

{   0: {   0: {'S': 'str1', 'T': 4, 'V': 0x3ff},
           1: {'S': 'str2', 'T': 5, 'V': 0x2ff}},
    1: {   0: {'S': 'str3', 'T': 8, 'V': 0x1ff},
           1: {'S': 'str4', 'T': 7, 'V': 0x0ff}},
......
}

It's a 2D dictionary basically.它基本上是一个二维字典。 The innermost dict follows {Str: str, str:int, str:int}, while its outer dict always has integer as the key to index.最里面的字典遵循 {Str: str, str:int, str:int},而它的外部字典总是以 integer 作为索引的键。

Is there a way for Pydantic to validate the data-type and data structure? Pydantic 有没有办法验证数据类型和数据结构? I mean if someone changes the data with a string as a key to the outer dict, the code should prompt an error.我的意思是如果有人用一个字符串作为外部字典的键更改数据,代码应该提示错误。 Or if someones tweaks the inner dict with putting 'V' value to a string, a checker needs to complain about it.或者,如果有人通过将“V”值赋给字符串来调整内部字典,则检查员需要对此进行投诉。

I am new to Pydantic, and found it always requires a str-type field for any data... Any ideas?我是 Pydantic 的新手,发现它总是需要一个 str 类型的字段来存储任何数据……有什么想法吗?

You could use Dict as custom root type with int as key type (with nested dict).您可以将Dict用作​​自定义根类型,并将int用作键类型(使用嵌套 dict)。 Like so:像这样:

from pydantic import BaseModel, StrictInt
from typing import Union, Literal, Dict

sample = {0: {0: {'S': 'str1', 'T': 4, 'V': 0x3ff},
              1: {'S': 'str2', 'T': 5, 'V': 0x2ff}},
          1: {0: {'S': 'str3', 'T': 8, 'V': 0x1ff},
              1: {'S': 'str4', 'T': 7, 'V': 0x0ff}}
          }


# innermost model
class Data(BaseModel):
    S: str
    T: int
    V: int


class Model(BaseModel):
    __root__: Dict[int, Dict[int, Data]]


print(Model.parse_obj(sample))

Just to share an alternative option - convtools models ( docs | github ).只是为了分享一个替代选项 - convtools 模型文档| github )。

It works in validate-only mode unless you explicitly tell it to cast types.它在仅验证模式下工作,除非您明确告诉它强制转换类型。 And it doesn't use unsafe type casting by default ( eg casting 1.5 to 1 is not fine ).而且默认情况下它不使用不安全的类型转换(例如,将1.5转换为1是不好的)。

from typing import Dict, Literal, Union
from convtools.contrib.models import DictModel, build

sample = {
    0: {
        0: {"S": "str1", "T": 4, "V": 0x3FF},
        1: {"S": "str2", "T": 5, "V": 0x2FF},
    },
    1: {
        0: {"S": "str3", "T": 8, "V": 0x1FF},
        1: {"S": "str4", "T": 7, "V": 0x0FF},
    },
}


# innermost model
class Data(DictModel):
    S: str
    T: int
    V: int


obj, errors = build(Dict[int, Dict[int, Data]], sample)
"""
>>> In [58]: obj
>>> Out[58]:
>>> {0: {0: Data(S='str1', T=4, V=1023), 1: Data(S='str2', T=5, V=767)},
>>>  1: {0: Data(S='str3', T=8, V=511), 1: Data(S='str4', T=7, V=255)}}
"""

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM