Python3 递归查找json中的key所在的位置

First.No bullshit.Just show the code.And the result.

# coding:utf8
import json

# source code URL: https://blog.csdn.net/weixin_42744102/article/details/99722187
class FindKey(object):
    def __init__(self, obj):
        self.json_object = None
        if isinstance(obj, str):
            self.json_object = json.loads(obj)
        elif obj != None:
            self.json_object = obj
        else:
            raise TypeError("Unexpected object type.Can not read from NoneType")

    def get_obj_contain_key(self, key):
        result_list = []
        self.__search_obj_contain_key(
            json_object=self.json_object,
            old_path="", 
            key=key, 
            result_list=result_list)
        return result_list

    def __search_obj_contain_key(self, json_object, old_path:str, key, result_list):
        if isinstance(json_object, dict):
            for k,v in json_object.items():
                if k == key:
                    result_list.append(
                        {
                            "path": old_path,
                            "obj": json_object
                        }
                    )
                if isinstance(v, dict) or isinstance(v, list):
                    self.__search_obj_contain_key(
                        json_object=v, 
                        old_path= old_path + "[\"{}\"]".format(k), 
                        key=key, 
                        result_list=result_list
                    )
        elif isinstance(json_object, list):
            tmp_index = 0
            for item in json_object:
                if item == key:
                    result_list.append(
                        {
                            "path": old_path,
                            "obj": json_object
                        }
                    )
                if isinstance(item, dict) or isinstance(item, list):
                    self.__search_obj_contain_key(
                        json_object=item, 
                        old_path= old_path + "[{}]".format(tmp_index), 
                        key=key, 
                        result_list=result_list
                    )
                tmp_index += 1
        return None

测试代码:

json_str = "{\"a_dict\":{\"a_list\":[\"item1\", \"ip\", \"item2\"]}, "+\
    "\"ip\":\"8.8.8.8\", \"b_dict\":{\"ip\":\"192.168.1.1\", "+\
    "\"c_dict\":{\"ips\":[{\"ip\":\"192.168.1.2\"},"+\
        "{\"ip\":\"192.168.1.3\"},{\"ip\":\"192.168.1.4\"}]}  }   }"

print(json_str)

json_obj = json.loads(json_str)

print(json_obj)

tool = FindKey(json_obj)
res = tool.get_obj_contain_key("ip")
for item in res:
    print("path=",item["path"])
    print("obj=",item["obj"])

运行结果如下:

{"a_dict":{"a_list":["item1", "ip", "item2"]}, "ip":"8.8.8.8", "b_dict":{"ip":"192.168.1.1", "c_dict":{"ips":[{"ip":"192.168.1.2"},{"ip":"192.168.1.3"},{"ip":"192.168.1.4"}]}  }   }
{'a_dict': {'a_list': ['item1', 'ip', 'item2']}, 'ip': '8.8.8.8', 'b_dict': {'ip': '192.168.1.1', 'c_dict': {'ips': [{'ip': '192.168.1.2'}, {'ip': '192.168.1.3'}, {'ip': '192.168.1.4'}]}}}
path= ["a_dict"]["a_list"]
obj= ['item1', 'ip', 'item2']
path=
obj= {'a_dict': {'a_list': ['item1', 'ip', 'item2']}, 'ip': '8.8.8.8', 'b_dict': {'ip': '192.168.1.1', 'c_dict': {'ips': [{'ip': '192.168.1.2'}, {'ip': '192.168.1.3'}, {'ip': '192.168.1.4'}]}}}
path= ["b_dict"]
obj= {'ip': '192.168.1.1', 'c_dict': {'ips': [{'ip': '192.168.1.2'}, {'ip': '192.168.1.3'}, {'ip': '192.168.1.4'}]}}
path= ["b_dict"]["c_dict"]["ips"][0]
obj= {'ip': '192.168.1.2'}
path= ["b_dict"]["c_dict"]["ips"][1]
obj= {'ip': '192.168.1.3'}
path= ["b_dict"]["c_dict"]["ips"][2]
obj= {'ip': '192.168.1.4'}

发展自这篇博客,戳我去看

测试代码运行结果解读:
测试代码里的最后一个for循环里的两句print,第一个print是输出的是 访问包含关键字key的那个对象在json_obj里的路径,表示 keyjson_obj["a_dict"]["a_list"] 这个对象里找到了。第二个print直接输出这个对象的内容。

当然我知道,还有的人只想搜索json对象里面所有的键值对,只搜键,不搜值,只想获取键自身的值是key的父元素。不过我觉得我的这个demonstration已经足够了,稍微改动一下就能实现这个需求,所以就没搞。真的想实现也很简单,就是把第44~50行代码注释掉或删掉就行了。

好啦。不好的代码,我当然要吐槽一下。原作者写的代码是真的不敢恭维。
结果生成了,应当立即返回。编程提倡尽量减少全局变量,而且结果暂存在class里面并没有意义,所以搞了个什么 self.result_list 除了实现偷懒式的全局变量应付递归需要修改同一个变量的需求,愣是没有看明白有什么用。要知道Python里面,变量都是引用对象的id,无论递归多少次,栈里的所有函数引用的result_list 依然是同一个变量,没有翻倍的内存开销。

另外吐槽一下,我搜了度娘好一会儿,居然找不到满足我这个需求的小demonstration,看了那博主的文章,以为是我需要的,结果不是我需要的,拿来用甚至重写了整个代码……找到轮子又重新造轮子,有苦说不出。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值