验证输入字典模式

时间:2020-02-27 06:31:49

标签: python dictionary nested

我有一个这样的Python输入字典模式,

SCHEMA = {
    'mode': ('mode_1', 'mode_2', 'mode_3'),
    'method': ('method_1', 'method_2'),
    'other': {
        'x1': [1, 365],
        'x2': [0., 1.0]
    }

}

我要验证给定的输入字典,

inp = {
    'mode': 'mode_1',
    'method': 'method_1',
    'other': {
        'x1': 1,
        'x2': 1.0
    }

}
  1. 包含相同的键
  2. 如果任何值是字典,请检查该字典是否也具有相同的键
  3. 检查输入dict的值是否在架构范围内。例如,对于键“模式”,输入字典的值应为('mode_1', 'mode_2', 'mode_3')。对于所有键值对来说,都是明智的选择。
  4. 如果SCHEMA中值的类型为列表,我还想检查输入dict中对应的值是否大于value [0]且小于value [1]

我可以考虑使用循环来实现。但是无法想到一种通用的方法。如果我只是遍历两个字典并比较它们的值,那么如果架构发生更改,就必须重写逻辑。

是否有任何直接的方法来验证模式?

3 个答案:

答案 0 :(得分:3)

您可以尝试使用此递归功能:

def validate(input_, db): 
    for k,v in input_.items(): 
        if isinstance(v, dict): 
            return validate(v, db.get(k)) 
        else: 
            if v not in db.get(k): 
                return False 
    return True 

然后您将其命名为:

In [21]: validate(inp, SCHEMA)                                                                                                                                                                                     
Out[21]: True

如果将inp更改为:

In [16]: inp = { 
    ...:     'mode': 'mode_2', 
    ...:     'method': 'method_2', 
    ...:     'other': { 
    ...:         'x1': 4, # This is not valid
    ...:         'x2': 1.0 
    ...:     } 
    ...:  
    ...: }                                                                                                                                                                                                         

In [17]: validate(inp, SCHEMA)                                                                                                                                                                                     
Out[17]: False

In [20]: inp = { 
    ...:     'mode': 'mode_2', 
    ...:     'method': 'method_2', 
    ...:     'other': { 
    ...:         'x1': 1, 
    ...:         'x2': 1.0 
    ...:     } 
    ...:  
    ...: }                                                                                                                                                                                                         
In [21]: validate(inp, SCHEMA)                                                                                                                                                                                     
Out[21]: True

答案 1 :(得分:2)

字典就像json,因此您可以使用jsonschema:

 import json

 from jsonschema import validate

 # A sample schema, YOU WILL HAVE TO DESIGN ONE .
 schema = {
     "type" : "object",
     "properties" : {
         "price" : {"type" : "number"},
         "name" : {"type" : "string"},
     },
 }

测试

# If no exception is raised by validate(), the instance is valid.
validate(instance={"name" : "Eggs", "price" : 34.99}, schema=schema)



validate(instance={"name" : "Eggs", "price" : "Invalid"}, schema=schema) 

#error

Traceback (most recent call last):
ValidationError: 'Invalid' is not of type 'number'

有关更多详细信息,请检查documentation

要获取适用于您架构的有效Json Schema,可以使用this

只需替换' with " and () with []

答案 2 :(得分:-1)

您可以使用递归:

SCHEMA = {'mode': ('mode_1', 'mode_2', 'mode_3'), 'method': ('method_1', 'method_2'), 'other': {'x1': [1, 365], 'x2': [0.0, 1.0]}}
inp = {'mode': 'mode_1', 'method': 'method_1', 'other': {'x1': 1, 'x2': 1.0}}
def check(d, s):
    return all(b in s[a] if not isinstance(b, dict) else check(b, s[a]) for a, b in d.items())

print(check(inp, SCHEMA))

输出:

True

编辑:以上解决方案仅检查有效密钥的迭代中是否存在单个密钥。但是,要处理更具体的检查(例如您的第四个条件),可以为不同的类型构建处理程序:

t = {'tuple':lambda x, y:x in y, 'list':lambda x, y:x > y[0] and x < y[-1]}
def check(d, s):
   return all(check(b, s[a]) if isinstance(b, dict) else t[type(s[a]).__name__](b, s[a]) for a, b in d.items())