新手区 测试工具构建过程中字典列表多层嵌套取值

LEFT · June 14, 2018 · Last by HazeMaker replied at January 21, 2019 · 1475 hits

最近一段时间,公司在着手开发一些测试相关工具,个人参与过程中遇到了字典列表多层嵌套的取值问题,关于此问题的解决方案,自己的一些拙见,敬请指正。

# 获取字典中的objkey对应的值,适用于字典列表嵌套
# test:字典
# objkey:目标key
# default:找不到时返回的默认值
# tmp_list:数据存储列表
# 字典遍历,遍历数据是字典,自执行,是列表执行列表
# 列表遍历,遍历数据是列表,自执行,是字典执行字典
#key值唯一
def list_get(test,objkey,default,tmp_list):
    for i in test:
        if isinstance(i,dict):
            dict_get(i,objkey,default,tmp_list)
        elif isinstance(i,list):
            list_get(i,objkey,default,tmp_list)

def dict_get(test,objkey,default,tmp_list):
    for k,v in test.items():
        if k != objkey:
            if isinstance(v,dict):
                dict_get(v,objkey,default,tmp_list)
            elif isinstance(v,list):
                list_get(v,objkey,default,tmp_list)
        else:
            k == objkey
            tmp_list.append(v)
    return tmp_list[0]
#test:字典
#objkey:目标key
#objupkey:目标上级key
#key值重复,筛选指定key值
def list_get(test, objkey,objupkey, default, tmp_list):
    for i in test:
        if isinstance(i, dict):
            dict_get(i, objkey,objupkey, default, tmp_list)
        elif isinstance(i, list):
            list_get(i, objkey,objupkey, default, tmp_list)


def dict_get(test, objkey,objupkey, default, tmp_list):
    for k, v in test.items():
        if  k != objupkey :
            if isinstance(v, dict):
                dict_get(v, objkey,objupkey, default, tmp_list)
            elif isinstance(v, list):
                list_get(v, objkey,objupkey, default, tmp_list)
        elif k == objupkey :
            if isinstance(v, list):
                for e in v:
                    if isinstance(e, dict):
                        for u,w in e.items():
                            if u == objkey:
                                if w != None:
                                    tmp_list.append(w)
            elif isinstance(v, dict):
                for u, w in v.items():
                    if u == objkey:
                        if w != None:
                            tmp_list.append(w)
    return tmp_list
共收到 8 条回复 时间 点赞

定义一个词法解析规则,比如 “person.0.name.alias”,然后 split 后,再遍历解析,参考 httprunner

https://github.com/HttpRunner/HttpRunner/blob/master/httprunner/utils.py#L173:5

LEFT #2 · June 14, 2018 Author
chu 回复

好的🙏,去参考学习一下

定义一个词法解析规则,比如 “person.0.name.alias”,然后 split 后,再遍历解析,参考 httprunner

这种访问形式,python 的话有现成的库 addict 传送门

LEFT #4 · June 14, 2018 Author
chen 回复

我在一个帖子里看到了你的回复,准备尝试,正在看 addict 的源码

LEFT 回复

👍 好学!

目前我也在做类似的内容,字典和列表互相嵌套,想直接作对比,看两者是否是包含关系。主要参考了你的代码,但觉得自己写的内容,过于繁琐,想了解下你后续的探索。

代码如下:

def compare_json(responce_data, check_data):
    if isinstance(responce_data, dict) and isinstance(check_data, dict):
        compare_json = compare_dict(responce_data, check_data)
    elif isinstance(responce_data, list) and isinstance(check_data, list):
        compare_json = compare_list(responce_data, check_data)
    else:
        compare_json = False
        print "Please check responce_data: %s, check_data: %s. They are not dict or list." % (responce_data, check_data)
        return compare_json
    if compare_json:
        print "responce_data: %s\ncheck_data: %s\nCheck Success!" % (responce_data, check_data)
    else:
        print "responce_data: %s\ncheck_data: %s\nCheck Fail!" % (responce_data, check_data)

def compare_dict(all_dict, check_dict):
    global compare_dict_status
    for (check_key, check_value) in check_dict.items():
        for (all_key, all_value) in all_dict.items():
            compare_dict_status = False
            if operator.eq(check_key, all_key):
                if isinstance(check_value, dict) and isinstance(all_value, dict):
                    #print "Dict::Dict check_value is %s, all_value is %s" % (check_value, all_value)
                    compare_dict_status = compare_dict(all_value, check_value)
                    if compare_dict_status:
                        break
                elif isinstance(check_value, list) and isinstance(all_value, list):
                    #print "List::List check_item is %s, all_item is %s" % (check_value, all_value)
                    compare_dict_status = compare_list(all_value, check_value)
                    if compare_dict_status:
                        break
                else:
                    if operator.eq(check_value, all_value):
                        print "%s:%s is in the %s" % (check_key, check_value, all_dict)
                        compare_dict_status = True
                        break
        if not compare_dict_status:
            print "Can't find %s:%s in the %s" % (check_key, check_value, all_dict)
            return compare_dict_status
    return compare_dict_status

def compare_list(all_list, check_list):
    global compare_list_status
    for check_item in check_list:
        for all_item in all_list:
            compare_list_status = False
            if isinstance(check_item, list) and isinstance(all_item, list):
                compare_list_status = compare_list(all_item, check_item)
                #print "List::List check_item is %s, all_item is %s, compare_list_status is %s" % (check_item, all_item, compare_list_status)
                if compare_list_status:
                    break
            elif isinstance(check_item, dict) and isinstance(all_item, dict):
                compare_list_status = compare_dict(all_item, check_item)
                #print "Dict::Dict check_item is %s, all_item is %s, compare_list_status is %s" % (check_item, all_item, compare_list_status)
                if compare_list_status:
                    break
            else:
                if operator.eq(check_item, all_item):
                    print "%s is in the %s" % (check_item, all_list)
                    compare_list_status = True
                    break
        if not compare_list_status:
            print "Can't find %s in the %s" % (check_item, all_list)
            return compare_list_status
    return compare_list_status
if __name__ == '__main__':
    all_list = ["1", "2", "3", "4", "5", {"test1": "1", "test2": "2", "test3": "3", "test9": [{"test6": "6"}, {"test7": "7"}, {"test8": "8"}], "test4": {"x": "9", "y": "0"}, "test5": "5"}]
    check_list = ["3", "5", {"test3": "3", "test4": {"y": "0"}, "test9": [{"test7": "7"}]}]
    print compare_json(all_list, check_list)
chen 回复

请教一下,这个 addict 支持 python 2 的 utf-8 么?
{'name_1': {u'msg': u'ok', u'code': u'0', u'data': {u'regionPath': u',root000000,c10e92a6-c090-4955-bdab-63eba5965c0a,', u'leaf': True, u'regionStatus': 0, u'dataVersion': 328, u'regionCodeStyle': u'none', u'indexCode': u'c10e92a6-c090-4955-bdab-63eba5965c0a', u'regionId': u'c10e92a6-c090-4955-bdab-63eba5965c0a', u'parentIndexCode': u'root000000', u'regionType': 0, u'regionCode': u'', u'parentId': u'root000000', u'disOrder': 91, u'regionDesc': u'', u'regionName': u'test1'}}}
这样的要如何处理?

需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up