I am using Python to test a REST API. I get a response message as json and want to check each field. I have created a check_json function and check against a checker dictionary. The checker dictionary has a string key which is the name of the key in json with value a tuple (a pair) with first bool parameter, whether item is mandatory and second parameter either an object to do direct compare or a function to add more involved checking functionality.
I make the check like this:
r= check_json(myjson, checker)
where r is the result in format: 'field': True or False - dependent on whether check passed or failed
The code is a little messay with lots of global functions. One idea was to include the is checking functions in check_json. I have been told that I could also use closures. But how?
Here is my code:
# 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)