json_tools是python的一个第三方模块,用于比对两个目标json是否相等,如果相等则返回True,否则返回包含不相等项的list;
但是如果两个目标json中都包含list,且两个list原本是相同的,只是list中元素位置不一样。而json_tools是默认用两个list中相同位置的元素进行比对,这样原本一样的list比对的结果是不相等的了。
如a=[a,b,c,d],b=[a,c,b,d],这两个list本是一样的,但是json_tools是用a==a,b==c,c==b,d==d进行对比,其结果自然是false;
我的算法是以a列表为模板,一个元素一个元素遍历b列表,如果在b列表中发现一样的元素,则将其调到与模板a列表中元素一样的位置。如果没有找到一样的元素,则寻找不一致元素最少的项(实际上json中list的元素都是dict)
具体代码如下:
#coding:utf-8
import json_tools,re,unicodedata
class JSONToolsExt(object):
#expectedvalue,response是需要比对的两个json
def isDiff(self,expectedvalue, response):
expdict=expectedvalue
respdict=response
result = json_tools.diff(expectedvalue, response) # 使用json_tools模块的diff方法比较两个json是否一致
other=None
if(result==True): #如果一致则直接返回True
return True
elif(len(result)==0):
return True
else:
result_leng=len(result)
for i in range(result_leng):
if(type(result[i])==type({})):
keys=result[i].keys()
for key in keys:
if(key=='replace'):
k_list=result[i].get(key).split('/')
fv=False
for k1 in k_list:
v = self.is_number(k1)
if(v):
fv=True
break
if(fv):
value_list=result[i].get(key)[1:].split('/')
for j in range(len(value_list)-1):
if(self.is_number(value_list[j])):
value_list=value_list[:j]
break
for k in range(len(value_list)):
expdict=expdict.get(value_list[k])
respdict=respdict.get(value_list[k])
# if(type(expdict)==type([]) and type(respdict)==type([])):
templist=self.synchroJSONList(expdict,respdict) #expdict,respdict其实是list
other=self.changeList(value_list,response,templist)
result=json_tools.diff(expectedvalue, other)
break
else:
break
if (result == True):
return True
elif (len(result) == 0):
return True
else:
result_i_keys=result[i].keys()
replace=None
v_b=[]
for key in result_i_keys:
if(key=='replace'):
replace=key
v_b = re.findall("d+", result[i].get(replace))
break
if(replace=='replace' and v_b):
break
return result
def synchroJSONList(self,explist=[],resplist=[]): #同步json中的list顺序
templist=[]
if(type(explist)==type([]) and len(explist)>0):
for exp in explist:
leng=len(resplist)
for resp in resplist:
res=json_tools.diff(exp,resp)
if(res==True):
templist.append(resp)
resplist.remove(resp)
break
if(leng==len(resplist)):
likely=self.mostlikely(exp,resplist)
templist.append(likely)
resplist.remove(likely)
return templist
def mostlikely(self,exp,resplist): #寻找最可能的项
resp=resplist[0]
num=len(json_tools.diff(exp, resplist[0]))
for i in range(1,len(resplist)):
res = json_tools.diff(exp, resplist[i])
if(len(res)<num):
resp = resplist[i]
num=len(res)
return resp
def changeList(self,value_list,respdict,templist): #将新的列表替换老列表
n=0
r_bat=respdict
for i in range(len(value_list)-1):
r_bat=r_bat.get(value_list[i])
vs=value_list[len(value_list)-1]
r_bat[vs]=templist
return respdict
def is_number(self,s): #判断字符串s是否是数值
try:
float(s)
return True
except Exception as e:
pass
try:
unicodedata.numeric(s)
return True
except Exception as e:
pass
return False