声名
初学Python,代码很糙,只是为了记录和大家相互探讨一下改进的办法。
想法
最近做Python处理的Dict和Json数据太多了,一个一个的判断in太麻烦了,于是想试试看能不能用自己的想法实现一个类似Validate验证器的东西。 这份代码说是验证器太草率了。
主要是针对Dict进行值的验证。
代码
class D_JValidator:
"""简易验证器
:rules 验证规则
{
"name.phone":[
{
'type': 'require',
'message': '手机必须填写'
}
],
"cl1.0.name":[
{
'type': 'require',
'message': '名称必须'
},{
'type': 'str',
'message': '名称必须是字符串'
}
]
}
"""
def __init__(self, rules:dict) -> None:
if not rules:
raise Exception("rules is must!")
if not isinstance(rules, dict):
raise Exception("rules is Only dict!")
self.rules = rules
def _dict_have_key(self, Data, nodes:str) -> bool:
"""判断dict里是否有节点路径"""
if not isinstance(Data, (Dict,List)):
raise Exception("Data is Only Dict/List!")
if not isinstance(nodes, str):
raise Exception("nodes is Only str!")
# 存储dict下一个传递信息
Cache = None
# 拆分节点路径
nodes_list = nodes.split(".")
# 获取当前元素的类型
now_node_type = str(type(Data))
# 判断节点是否是数字
if nodes_list[0].isdigit():
# 判断当前元素是否是list类型,因为节点是下标。 同时判断node有没有在下标范围内。
if not now_node_type.startswith("<class 'list'>") or (len(Data) - 1) < int(nodes_list[0]):
return False
Cache = Data[int(nodes_list[0])]
else:
# 直接判断当前的节点名称在不在Data中
if nodes_list[0] not in Data:
return False
Cache = Data[nodes_list[0]]
# 递归下一层
if len(nodes_list) >= 2:
nodes_list.pop(0)
return self._dict_have_key(
Data=Cache,
nodes='.'.join(nodes_list)
)
return Cache
def _check_rule(self, Data, rule, node) -> bool:
"""解析验证规则及验证数据是否符合验证规则"""
# 判断Data为False说明节点压根不存在。
if not Data:
# 只需要关注rule是不是require。
if rule['type'] == 'require':
raise Exception(rule['message'])
else:
return True
# 规则验证
if rule['type'] == 'require':
# 验证数据是不是为空, 如果是str先去掉空格
if isinstance(Data, str):
Data = Data.strip()
if not Data:
if 'message' in rule and rule['message']:
raise Exception(f"{node}: {rule['message']}")
else:
raise Exception(f"{node} is require")
elif rule['type'] == 'int':
# 验证数据是不是int
if not isinstance(Data, int):
if 'message' in rule and rule['message']:
raise Exception(f"{node}: {rule['message']}")
else:
raise Exception(f"{node} is not int")
elif rule['type'] == 'str':
# 验证数据是不是str
if not isinstance(Data, str):
if 'message' in rule and rule['message']:
raise Exception(f"{node}: {rule['message']}")
else:
raise Exception(f"{node} is not str")
return True
def check(self, Data:dict):
"""验证
:Data 验证的数据
"""
if not isinstance(Data, dict):
raise Exception("Data is Only dict!")
# 循环验证规则
for rule in self.rules:
# 遍历全部的验证规则进行逐条判断
for ruls_node_path in self.rules:
# 判断路径节点是否存在
Dict_Child = self._dict_have_key(
Data=Data,
nodes=ruls_node_path
)
# 遍历验证规则
for rule_type in self.rules[ruls_node_path]:
self._check_rule(Dict_Child, rule_type, ruls_node_path)
if __name__ == "__main__":
data = {
"s2": "1"
}
rules = {
"s.0":[
{
'type': 'str',
'message': '必须是字符串'
}
],
"s2":[
{
'type': 'int',
'message': '必须是数字'
},{
'type': 'require',
'message': '必须有值'
}
]
}
V = D_JValidator(
rules=rules
)
V.check(
Data=data
)