Python修改嵌套字典的key值
最近在搞接口测试的时候发现了一个比较有趣的json入参数,结构如下:
json = {"aa": "33", "bb": [{"gg": "33"}, {"jj": [{"gg": "33"}, {"haha": [{"gg": "33"}, {"yyyu": [{"yy": "希望调试成功", "kk": {"uu": "hr", "lll": {"gg": "33"}}}]}]}]}], "gg": "33"}
观察该json数据,我们发现有大量的相同的key(gg),并且这些key的value值都是一样的,那么我们需要修改所有key(gg)的值,应该怎么做呢?
提问:为什么会有这么有趣的入参数据?
我也不知道,因为公司的出库单的业务数据就有这么可怕和奇葩的数据,只是没有本文中举例的那么夸张
第一:我们可以把这个数据封装成一个函数,实现如下所示:
def data(gg): dict_data = {'aa': '33', 'bb': [{'gg': gg}, {'jj': [{'gg': gg}, { 'haha': [{'gg': gg}, {'yyyu': [{'yy': '希望调试成功', 'kk': {'uu': 'hr', 'lll': {'gg': gg}}}]}]}]}], 'gg': gg} return dict_data print(data('hahaha'))
这样很完美的解决我们的问题了。完美,解题结束......enenen、但是这会引生出另一个问题,就是每次接口改动需要去修改代码,不便于工具化(虽然在接口自动化后接口不太可能会发生改动),
对于测试来说不可能人人都去搞工具化,但是你不能没有一个工具化的心。
OK,目标明确了,那么我们需要搞个好的思路了,但是在这之前我们不得不先了解一下python对于字典的操作:
首先,最简单的方法是直接创建字典,dict={"name":"张三","age":"23"}
再次,先创建一个空字典,然后对字典进行赋值或者修改,具体如下图所示:
从上图中可以看出,我们是可以直接对字典进行操作的结构为dict["key"] = value,dict["key"] 表示字典的key,value表示key的值,简单点说就是字典里面的元素,
以及元素的值是什么,但是有一点要清楚,字典里面key的值它可以是一个字符串,可以是数字,可以是列表,可以是字典。(说明:在python中json串可以理解是一个字典)。
不难理解,我们在上图中直接对一个空字典定义了元素和元素值,那么对嵌套字典改如何进行操作呢?这里以比较有趣的json入参数来进行讲解:
如上图所示,每一个需要修改的key都需要指明路径,所以非常麻烦,非常难搞,随着明细的增加,说不定形同名称的key还会更多,然后有需要手动指明,
这种方法还不如用函数去修改key的值,所以还需要再想想办法。
想不到更多的表达语言,直接看如下代码:
dict_data = {'aa': '33', 'bb': [{'gg': ''}, {'jj': [{'gg': 'gg'}, { 'haha': [{'gg': 'gg'}, {'yyyu': [{'yy': '希望调试成功', 'kk': {'uu': 'hr', 'lll': {'gg': 'gg'}}}]}]}]}], 'gg': 'gg'} key = 'gg' def update(key,dict_data): #判断需要修改的key是否在初始字典中,在则修改 if key in dict_data: #将key为'gg'的值修改成'张三' dict_data[key]='张三' #print(dict_data) #循环字典获取到所有的key值和value值 for keys,values in dict_data.items(): #判断valus值是否为列表或者元祖 if isinstance(values,(list,tuple)): #循环获取列表中的值 for i in values: #判断需要修改的值是否在上一个循环出的结果中,在则修改 if key in i and isinstance(i,dict): #调用自身修改函数,将key的值修改成'张三' update(key,i) else: #否者则调用获取value函数 get_value(i) elif isinstance(values,dict): if key in values: update(key,values) else: for keys,values in values.items(): if isinstance(values,dict): update(key, values) else: #循环获取原始字典的values值 for keys,values in dict_data.items(): #判断values值是否是列表或者元祖 if isinstance(values,(list,tuple)): #如果是列表或者元祖则循环获取里面的元素值 for i in values: #判断需要修改的key是否在元素中 if key in i: #调用修改函数修改key的值 update(key,i) else: #否则调用获取values的值函数 get_value(i) #判断values值是否为字典 elif isinstance(values,dict): #判断需要修改的key是否在values中 if key in values: #调用修改函数修改key的值 update(key,values) else: #获取values值的函数 get_value(values) return dict_data def get_value(tt): #循环获取values的值 for values in tt.values(): #判断循环出的value的值是否为列表或者元祖 if isinstance(values, (list,tuple)): #如果为列表或者元祖则循环获取列表或者元祖中的值 for i in values: #判断需要修改的值是否在循环出的值中,且i为字典 if key in i and isinstance(i,dict): #调用修改函数,将key的值修改为'张三' update(key, i) else: #否则调用获取value函数 get_value(i) elif isinstance(values,dict): if key in values: update(key, values) else: get_value(values) update(key,dict_data)
如上图代码所示:总的来说就是将字典循环判断曲直并修改,然后就完事了咯。
这样做的好处是,我们在做接口自动化的时候可以将数据与脚本分离,只需在excel中维护好入参,指定获取返回变量值即可