Reputation: 11917
I have a schema for a input dict in Python that goes like this,
SCHEMA = {
'mode': ('mode_1', 'mode_2', 'mode_3'),
'method': ('method_1', 'method_2'),
'other': {
'x1': [1, 365],
'x2': [0., 1.0]
}
}
I want to validate the given input dict,
inp = {
'mode': 'mode_1',
'method': 'method_1',
'other': {
'x1': 1,
'x2': 1.0
}
}
('mode_1', 'mode_2', 'mode_3')
. Like wise for all the key-value pair. I can think about doing it with loops. But can't think of a generalized way to do it. If I just looped over the two dicts and compared the values, I have to rewrite the logic if the schema changes.
Is there any straight forward way to validate the schema?
Upvotes: 2
Views: 2651
Reputation: 71451
You can use recursion:
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))
Output:
True
Edit: the solution above simply checks that a single key exists in an iterable of valid keys. However, to handle more specific checks (such as your fourth condition), you can build handlers for different types:
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())
Upvotes: -1
Reputation: 1306
Dictionary are like json so you can use 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"},
},
}
TESTING
# 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'
For more details check the documentation.
To get valid Json Schema for your schema you can use this.
Just replace ' with " and () with []
.
Upvotes: 3
Reputation: 11073
You can try this recursive function:
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
Then you call it:
In [21]: validate(inp, SCHEMA)
Out[21]: True
if you change your inp to:
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
or
In [20]: inp = {
...: 'mode': 'mode_2',
...: 'method': 'method_2',
...: 'other': {
...: 'x1': 1,
...: 'x2': 1.0
...: }
...:
...: }
In [21]: validate(inp, SCHEMA)
Out[21]: True
Upvotes: 3