接口测试 python 分享一个通过 (key1.key2.key3) 形式获取嵌套字典值的方法

重拾 · 2017年03月21日 · 最后由 838863149 回复于 2022年06月21日 · 4945 次阅读

最近在做接口自动化测试,响应的内容大多数是多层嵌套的 json 数据,如果一层层的去剥,效率不高,脚本繁重,所以写了一个可以通过(key1.key2.key3)形式获取嵌套字典值的方法,如有不对或者需要优化的地方欢迎指出。

def get_dict_value(date, keys, default=None):
    #default=None,在key值不存在的情况下,返回None
    keys_list = keys.split('.')
    #以“.”为间隔,将字符串分裂为多个字符串,其实字符串为字典的键,保存在列表keys_list里
    if isinstance(date,dict):
        #如果传入的数据为字典
        dictionary = dict(date)
        #初始化字典
        for i in keys_list:
            #按照keys_list顺序循环键值
            try:
                if dictionary.get(i) != None:
                    dict_values = dictionary.get(i)
                #如果键对应的值不为空,返回对应的值
                elif dictionary.get(i) == None:
                    dict_values = dictionary.get(int(i))
                #如果键对应的值为空,将字符串型的键转换为整数型,返回对应的值
            except:
                return default
                    #如果字符串型的键转换整数型错误,返回None
            dictionary = dict_values
        return dictionary
    else: 
        #如果传入的数据为非字典
        try:
            dictionary = dict(eval(date))
            #如果传入的字符串数据格式为字典格式,转字典类型,不然返回None
            if isinstance(dictionary,dict):
                for i in keys_list:
                    #按照keys_list顺序循环键值
                    try:
                        if dictionary.get(i) != None:
                            dict_values = dictionary.get(i)
                        #如果键对应的值不为空,返回对应的值
                        elif dictionary.get(i) == None:
                            dict_values = dictionary.get(int(i))
                        #如果键对应的值为空,将字符串型的键转换为整数型,返回对应的值
                    except:
                        return default
                            #如果字符串型的键转换整数型错误,返回None
                    dictionary = dict_values
                return dictionary
        except:
            return default

运行结果:
一:字典类型数据。

二:字典类型数据,包含的键为数字。

三:json 类型的字符串。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 19 条回复 时间 点赞

测试下这种 {"key":[{"subkey":"value"}]}

有个朋友分享过这段代码,大家可以试试。

class obj(object):
    def __init__(self, d):
        for a, b in d.items():
            if isinstance(b, (list, tuple)):
                setattr(self, a, [obj(x) if isinstance(x, dict) else x for x in b])
            else:
                setattr(self, a, obj(b) if isinstance(b, dict) else b)

d = {'a':1, 'b':{'c':2}, 'd':[{'e':1}]}

res = obj(d)
print res.a
print res.b.c
print res.d[0].e

python 的 json 模块不能搞这些事么?

可以参考这个addict

chen 回复

👍 原来还有这个库,实现起来好简单,非常感谢

zragon 回复

给力

孙高飞 回复

json 模块只用过来字符转字典,字典转字符,好像没看到有取值的

chen 回复

感谢分享

json 对象比字典对象复杂度高一点,接口测试里处理 json 可以这样做:

json.loads() 方法可以将字符串转化成 json 对象,如果不方便转换的类型,比如数据库涉及的 date,timestamp 类型,也可以通过 json.JSONEncoder 自己定义转化。

python 里 json 数据的取值也比较简单 ,基本就是 ob[key][index] 这样。

楼主的例子

ob = json.loads(data_a)
print ob["2"]["b"]["c"]

不过,等等,发现一个令我惊恐的问题,楼主给的字符串,第一层的 key 是 1?这个符合 json 的规范?
所以我刚试了一下,楼主的字符串用 json 模块 loads 不进,orz 我错了

@xeon 楼主,请教个问题,我的接口要求传入的 json 串按顺序,否则接口不认。python 读取字典是随机的,那么 json 串里面的参数也是随机排列的,有没有什么好的方法 。

独行数息 回复

json.dumps() 方法有个参数 sort_keys

剪烛 回复

这个只能按首字母排序 。而不是自定义顺序

重拾 #14 · 2017年03月24日 Author
剪烛 回复

是的,key 可能是字符,也可能是数字

独行数息 回复

自定义顺序或许可以看下 OrderedDict?

重拾 #16 · 2017年03月24日 Author
独行数息 回复

你参考一下

匿名 #17 · 2018年12月07日

如果是这种嵌套里面有多个相同的 key 呢,如下面的 second_key1 和 second_key2 呢?
{
'first_ke1': 'a',
'first_key2': [{'second_key1': 'b1', 'second_key2': 'c1'}, {'second_key1': 'b2', 'second_key2': 'c2'}, {'second_key1': 'b3', 'second_key2': 'c3'}]
}

chen 回复

帮了大忙了,太感谢!

{"f": 4, "a.b.c": 1, "a.b.d": 2, "a.e": 3, "d.1":"5"} ==可否实现转成==> {"a":{"b":{"c":1, "d":2}, "e": 3}, "f": 4, "d":[None, 5]}

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册