我有一本字典:
{
"checksum": "b884cbfb1a6697fa9b9eea9cb2054183",
"roots": {
"bookmark_bar": {
"children": [ {
"date_added": "12989159740428363",
"id": "4",
"name": "test2",
"type": "url",
"url": "chrome://bookmarks/#1"
} ],
"date_added": "12989159700896551",
"date_modified": "12989159740428363",
"id": "1",
"name": "bookmark_bar",
"type": "folder"
},
"other": {
"children": [ {
"date_added": "12989159740428363",
"id": "4",
"name": "test",
"type": "url",
"url": "chrome://bookmarks/#1"
} ],
"date_added": "12989159700896557",
"date_modified": "0",
"id": "2",
"name": "aaa",
"type": "folder"
},
"synced": {
"children": [ ],
"date_added": "12989159700896558",
"date_modified": "0",
"id": "3",
"name": "bbb",
"type": "folder"
}
},
"version": 1
}
一切都从“根”开始,它们有两种类型的数据:URL和文件夹,它们是字典。 如果它是一个文件夹,它必须有密钥'children',密钥的值是一个列表,我们可以在其中放入更多的URL和文件夹。
现在我想遍历这个嵌套字典,获取所有子文件夹中的URL,所以我写了一个函数:
def traverse(dic):
for i in dic:
if i['type'] == 'folder':
for j in traverse(i['children']):
yield j
elif i['type'] == 'url':
yield i
我可以这样使用它:
traverse(dictionary['roots']['bookmark_bar']['children'])
完美无缺。但它只是生成一个URL的字典,我不知道它在哪里。 我也希望得到这条路。我该怎么办?
答案 0 :(得分:5)
我的用例略有不同:我需要将表示客户端设置的可变深度JSON结构展平为键值对,以便存储在数据库中。我无法得到jsbueno的工作答案,因为我还需要一些可以处理没有明确列出或包含子项的案例,我修改它以满足我的需要:
def traverse(dic, path=None):
if not path:
path=[]
if isinstance(dic,dict):
for x in dic.keys():
local_path = path[:]
local_path.append(x)
for b in traverse(dic[x], local_path):
yield b
else:
yield path,dic
最终结果是我可以将这样的JSON字符串传递给我的脚本(具有可变深度),将其转换为嵌套的dicts:
{
"servers": {
"uat": {
"pkey": true,
"user": "testval",
"pass": true
},
"dev": {
"pkey": true,
"user": "testval",
"pass": true
}
}
}
在它上面运行生成器会创建一个像这样漂亮打印的列表:
([u'servers', u'uat', u'pkey'], True)
([u'servers', u'uat', u'user'], u'testval')
([u'servers', u'uat', u'pass'], True)
([u'servers', u'dev', u'pkey'], True)
([u'servers', u'dev', u'user'], u'testval')
([u'servers', u'dev', u'pass'], True)
其中,使用类似:
for x in traverse(outobj):
pprint(('.'.join(x[0]),x[1]))
然后可以将转换为我想要的键值对格式:
(u'servers.uat.pkey', True)
(u'servers.uat.user', u'testval')
(u'servers.uat.pass', True)
(u'servers.dev.pkey', True)
(u'servers.dev.user', u'testval')
(u'servers.dev.pass', True)
我知道在接受了接受的答案之后我会以这种方式发帖,但由于接受的答案对我不起作用,也许这个与结构无关的版本会帮助其他人!
答案 1 :(得分:1)
不确定我是否得到了你想要的东西,但你可能想要这样做:
def traverse(dic, path=None):
if not path:
path = []
for i in dic:
local_path = path[:].append(i)
if i['type'] == 'folder':
for j in traverse(i['children'], local_path):
yield j, local_path
elif i['type'] == 'url':
yield i, local_path
现在,您的函数会生成项目和一系列键,以便到达某个位置的项目。