驗證 JSON
手動完成驗證 JSON
資料
function
def validate(data, template):
# implement
# and return True/False
# in the case of False, return a string describing
# the first error encountered
# in the case of True, string can be empty
return state, error
result
That should return this:
validate(john, template) --> True, ''
validate(eric, template) --> False, 'mismatched keys: bio.birthplace.city'
validate(michael, template) --> False, 'bad type: bio.dob.month'
更好的做法 ⇒ 製作成 exception 取代 return codes and strings
def match_keys(data, valid, path):
data_keys = data.keys()
valid_keys = valid.keys()
extra_keys = data_keys - valid_keys #
missing_keys = valid_keys - data_keys
if extra_keys or missing_keys:
is_ok = False
missing_msg = ('missing keys:'+','.join({path+"."+str(key) for key in missing_keys})) if missing_keys else ''
extra_msg = ('extra keys:'+','.join({path+"."+str(key) for key in extra_keys})) if extra_keys else ''
return False, ' '.join((missing_msg, extra_msg))
else:
return True, None
def match_types(data, template, path):
for key, value in template.items():
if isinstance(value,dict):
template_type = dict
else:
template_type = value
data_value = data.get(key, object())
if not isinstance(data_value, template_type):
err_msg = ('incorrect type: ' + path + '.' + key +' -> expected ' + template_type.__name__ + ', found ' + type(data_value).__name__)
return False, err_msg
return True, None
def recurse_validate(data, template, path):
# key match
is_ok, err_msg = match_keys(data, template, path)
if not is_ok:
return False, err_msg
# data type
is_ok, err_msg = match_types(data, template, path)
if not is_ok:
return False, err_msg
# nested dictionaries
dictionary_type_keys = {key for key, value in template.items() if isinstance(value, dict)}
for key in dictionary_type_keys:
sub_path = path + '.' + str(key)
sub_template = template[key]
sub_data = data[key]
is_ok, err_msg = recurse_validate(sub_data, sub_template, sub_path)
if not is_ok:
return False, err_msg
return True, None