How can I remove need for these checking functions to be global
我正在使用Python测试RESTAPI。我得到一个作为JSON的响应消息,并希望检查每个字段。我已经创建了一个check json函数,并对照一个checker字典进行检查。checker字典有一个字符串键,它是json中键的名称,值是一个具有第一个bool参数的元组(一对),无论item是强制的,第二个参数是要进行直接比较的对象,还是添加更多相关检查功能的函数。
我是这样开支票的:
1 | r= check_json(myjson, checker) |
其中r是格式为"field"的结果:true或false-取决于检查是否通过或失败
代码有点混乱,有很多全局函数。其中一个想法是在check-json中包含is-checking函数。我被告知我也可以使用闭包。但是怎么做呢?
这是我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | # check nested json import json import collections import functools import datetime #this is json from GET session myjson = { "accessed":"Wed, 31 Jul 2013 13:03:38 GMT", "created":"Wed, 31 Jul 2013 13:03:38 GMT", "dnUrls": [ "http://135.86.180.69:8580/ucc/api/v1/session/dns/50000" ], "expires":"Wed, 31 Jul 2013 13:03:48 GMT", "modified":"Wed, 31 Jul 2013 13:03:38 GMT", "name":"KW50000", "person": { "employeeId":"KW50000", "firstName":"KW50000", "lastName":"Dev5" }, "previewRedirect": { "destination":"", "enabled": False, "setupEnabled": False } } def isDate(s): try: testdate = datetime.datetime.strptime(s, '%a, %d %b %Y %H:%M:%S GMT') return True except Exception: print"conversion to date failed" return False def isURL(l): count = 0 for item in l: count += 1 if item.startswith("http://") else (-1) return count > 0 def isAlnum(s): return s.isalnum() def isBool(s): return type(s) == bool def isAny(s): return True #checker object made up of dictionary with string key and tuple value (a pair) #tuple first filed is flag indicating whether key is mandatory or not. # tuple 2nd key is value to expect or a checker function checker = { "accessed": (True, isDate), "created": (True, isDate), "dnUrls": (True, isURL), "expires": (True, isDate), "modified": (True, isDate), "name": (True,"KW50000"), "person": (True, { "employeeId": (True, isAlnum), "firstName": (False, isAny), "lastName": (False, isAny) }), "previewRedirect": (True, { "destination": (False, isAny), "enabled": (True, isBool), "setupEnabled": (False, isBool) }) } # returns dictionary with key= fieldname, value = result, either True (Test Pass), False (test Failed) def check_json(obj, checker): """params json to check, template comparison object returns dictionary of keys to pass/fail values""" result = {} for k, (mFlag, chk) in checker.iteritems(): if not k in obj: result[k] = not mFlag elif isinstance(chk, collections.Callable): result[k] = chk(obj[k]) elif(isinstance(chk, collections.Mapping)): result[k] = check_json(obj[k], chk) else: result[k] = chk == obj[k] return result def with_and(v1, v2): return functools.reduce(with_and, v2.itervalues(), v1) if isinstance(v2, collections.Mapping) else v1 and v2 r= check_json(myjson, checker) print"r={}".format(r) isOK = functools.reduce(with_and, r.itervalues(), True) print"Result is {}: {}".format(isOK, r) |
号
这是一种可能的方法。您必须决定它是否更可读/可维护/等等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | # check nested json import collections from functools import reduce import datetime #this is json from GET session myjson = { "accessed":"Wed, 31 Jul 2013 13:03:38 GMT", "created":"Wed, 31 Jul 2013 13:03:38 GMT", "dnUrls": [ "http://135.86.180.69:8580/ucc/api/v1/session/dns/50000" ], "expires":"Wed, 31 Jul 2013 13:03:48 GMT", "modified":"Wed, 31 Jul 2013 13:03:38 GMT", "name":"KW50000", "person": { "employeeId":"KW50000", "firstName":"KW50000", "lastName":"Dev5" }, "previewRedirect": { "destination":"", "enabled": False, "setupEnabled": False } } # returns dictionary with key= fieldname, value = result, # either True (Test Pass), False (test Failed) def check_json(obj, checker): """params json to check, template comparison object returns dictionary of keys to pass/fail values""" result = {} for k, (mFlag, chk) in checker.items(): if not k in obj: result[k] = not mFlag elif isinstance(chk, collections.Callable): result[k] = chk(obj[k]) elif(isinstance(chk, collections.Mapping)): result[k] = check_json(obj[k], chk) else: result[k] = chk == obj[k] return result def isDate(s): try: datetime.datetime.strptime(s, '%a, %d %b %Y %H:%M:%S GMT') return True except Exception: print("conversion to date failed") return False #checker object made up of dictionary with string key and tuple value (a pair) #tuple first filed is flag indicating whether key is mandatory or not. # tuple 2nd key is value to expect or a checker function checker = { "accessed": (True, check_json.isDate), "created": (True, check_json.isDate), "dnUrls": (True, lambda l: (reduce(lambda c, v:\ c + (1 if v.startswith('http://') else -1), l, 0) > 0)), "expires": (True, check_json.isDate), "modified": (True, check_json.isDate), "name": (True,"KW50000"), "person": (True, { "employeeId": (True, lambda s: s.isalnum()), "firstName": (False, True), "lastName": (False, True) }), "previewRedirect": (True, { "destination": (False, True), "enabled": (True, lambda s: type(s) is bool), "setupEnabled": (False, lambda s: type(s) is bool) }) } def with_and(v1, v2): return functools.reduce(with_and, v2.values(), v1)\ if isinstance(v2, collections.Mapping) else v1 and v2 r = check_json(myjson, checker) print("r={}".format(r)) isOK = functools.reduce(with_and, r.values(), True) print("Result is {}: {}".format(isOK, r)) |
请注意,已经为python3修改了代码。主要的变化是尽可能使用