Pydantic 如何处理未知的字典键

Raa*_*mEE 5 python json pydantic

我有一个 json 对象,我想使用 Pydantic 进行验证。

我面临的问题是:

1 - 我不知道 JSON 中有多少个字段。下面的示例有 2 个键\字段:“225_5_99_0”和“225_5_99_1”

2 - 我不知道这种情况下的字段名称:它可以是“225_5_99_0”或“226_0_0_0”。我只知道他们遵守一些约定。

3 - 某些字段具有对模型字段名称无效的关键字,例如“*”键。我可以通过将字段名称别名为“星号”来克服这个问题。

关于处理此类 JSON 的最佳方法有什么想法吗?

{
    "225_5_99_0": {
        "*": {
            "flag": "",
            "group1": "225.5.99.0",
            "group_type": "M",
            "uptime": "0:11:23",
            "iif": {"lo5": {
                "flag": "R",
                "uptime": "0:44:41"
            }
            },
            "oil": {
                "bun_1215": {
                    "flag": "",
                    "join_time": "00:03:14",
                    "uptime": "0:42:27"
                },
                "bun_1218": {
                    "flag": "",
                    "join_time": "00:02:44",
                    "uptime": "0:44:41"
                }
            },
            "address": "100.100.100.100",
            "rp": "*",
            "source": "*",
            "upstream": "Joined(00:00:19)"
        }
    },
    "225_5_99_1": {
        "*": {
            "flag": "",
            "group1": "225.5.99.0",
            "group_type": "M",
            "uptime": "0:11:23",
            "iif": {"lo5": {
                "flag": "R",
                "uptime": "0:44:41"
            }
            },
            "oil": {
                "bun_1215": {
                    "flag": "",
                    "join_time": "00:03:14",
                    "uptime": "0:42:27"
                },
                "bun_1218": {
                    "flag": "",
                    "join_time": "00:02:44",
                    "uptime": "0:44:41"
                }
            },
            "address": "100.100.100.100",
            "rp": "*",
            "source": "*",
            "upstream": "Joined(00:00:19)"
        }
    },        
  }
}
Run Code Online (Sandbox Code Playgroud)

Raa*_*mEE 2

感谢@alex_noname的回复,我得到了我需要的东西。我在最后附上了完整的代码和打印输出。

继续我的问题中的各个部分:

1 - 我不知道 JSON 中有多少个字段。下面的示例有 2 个键\字段:“225_5_99_0”和“225_5_99_1”

Example必须将属性定义为字典,因此它成为嵌套对象的字典。

您还必须实现itergetitem以使Example类的行为像现在的 dict\list 一样。

另请参阅:自定义根类型


2 - 我不知道这种情况下的字段名称:它可以是“225_5_99_0”或“226_0_0_0”。我只知道他们遵守一些约定。

我定义:

UnderScoreNumbers = constr(regex=r'^[0-9_]*$')
...
__root__: Dict[UnderScoreNumbers, Dict]
Run Code Online (Sandbox Code Playgroud)

因此,键现在被验证为由数字和下划线组成的字符串,例如 225_5_99_0 等。


3 - 某些字段具有对模型字段名称无效的关键字,例如“*”键。我可以通过将字段名称别名为“星号”来克服这个问题。

我定义了一个带有别名“ ”的字段来使用 dict 的键“ ”,该键在 json 中是唯一的。我认为,如果您可以影响生成 json 的开发人员,建议避免使用不能是有效属性名称的字段,例如“*”、“123a”等。

asterisk: Dict[str, Dict] = Field(alias='*')


from typing import Dict

from pydantic import BaseModel, constr

example_dict = {
    "225_5_99_0": {
        "*": {
            "flag": "",
            "group1": "225.5.99.0",
            "group_type": "M",
            "uptime": "0:11:23",
            "iif": {"lo5": {
                "flag": "R",
                "uptime": "0:44:41"
            }
            },
            "oil": {
                "bun_1215": {
                    "flag": "",
                    "join_time": "00:03:14",
                    "uptime": "0:42:27"
                },
                "bun_1218": {
                    "flag": "",
                    "join_time": "00:02:44",
                    "uptime": "0:44:41"
                }
            },
            "address": "100.100.100.100",
            "rp": "*",
            "source": "*",
            "upstream": "Joined(00:00:19)"
        }
    },
    "225_5_99_1": {
        "*": {
            "flag": "",
            "group1": "225.5.99.0",
            "group_type": "M",
            "uptime": "0:11:23",
            "iif": {"lo5": {
                "flag": "R",
                "uptime": "0:44:41"
            }
            },
            "oil": {
                "bun_1215": {
                    "flag": "",
                    "join_time": "00:03:14",
                    "uptime": "0:42:27"
                },
                "bun_1218": {
                    "flag": "",
                    "join_time": "00:02:44",
                    "uptime": "0:44:41"
                }
            },
            "address": "100.100.100.100",
            "rp": "*",
            "source": "*",
            "upstream": "Joined(00:00:19)"
        }
    },        
  }
}

class Asterisk(BaseModel):
    asterisk: Dict[str, Dict] = Field(alias='*')

UnderScoreNumbers = constr(regex=r'^[0-9_]*$')


class Example(BaseModel):
    __root__: Dict[UnderScoreNumbers, Dict]

    def __iter__(self):
        return iter(self.__root__)

    def __getitem__(self, item):
        return self.__root__[item]


if __name__ == '__main__':
    e1 = Example.parse_obj(example_dict)
    for key in e1:
        print(f'{key}: {e1[key]}')
    print(e1)
    print('The End!')
Run Code Online (Sandbox Code Playgroud)

输出:

225_5_99_0: {'*': {'flags': '', ...
225_5_99_1: {'*': ...
__root__={'225_5_99_0': {'*': {'flags': '', ....
Run Code Online (Sandbox Code Playgroud)