【发布时间】:2025-12-13 19:05:03
【问题描述】:
我需要修改下面的json文件,test.json:
{
"install": {
"site": {
"acls": {
"dns": {
"authorized_ports": ["53:tcp", "53:udp"]
}
},
"network": {
"clusters": {
"__ip_range_1__": {
"dhcpstart": "__ip__",
"dhcpend": "__ip__",
"adminip": "__ip__"
},
"__ip_range_2__": {
"dhcpstart": "__ip__",
"dhcpend": "__ip__",
"adminip": "__ip__"
}
}
}
}
}
}
以上是缩写,原文件中还有很多条目。我每个站点都有几个这样的文件,因此__ip_range_x__ 在每个文件中都不同,每个 IP 也不同。我需要为每个 __ip_range_x__ 元素添加条目。新条目是存储在 mod.json 中的字典字典(下面为interface_config):
{
"path": "{install}{site}{network}{clusters}{*}",
"install" : {
"site": {
"network": {
"clusters": {
"__iprange": {
"interface_config": {
"framesize": "1500",
"framesize_vm": "1500"
}
}
}
}
}
}
}
我还需要在原始 json 文件的不同部分添加其他条目。
现在,我只是尝试遍历 test.json 中的所有元素。最终,我想为 test.json 中的每个元素构建一个路径,并将其与 mod.json 中的路径匹配以修改 test.json。但是,我无法在原始文件中打印所有元素。我当前的代码:
import json
import pprint
def traverse(d, path=None):
if path is None:
path = []
for item,val in d.iteritems():
if isinstance(item, dict):
for k,v in item.iteritems():
print k
traverse(v)
elif isinstance(item, list):
for j in item:
(traverse(j))
else:
print item
if isinstance(val, dict):
for k,v in val.iteritems():
print k
traverse(v)
elif isinstance(val, list):
for j in val:
(traverse(j))
with open("test.json", "r") as jf:
data = json.load(jf)
traverse(data)
上面的输出是:
$ ./now.py
install
site
acls
dns
authorized_ports
Traceback (most recent call last):
File "./now.py", line 51, in <module>
traverse(data)
File "./now.py", line 23, in traverse
traverse(v)
File "./now.py", line 23, in traverse
traverse(v)
File "./now.py", line 26, in traverse
(traverse(j))
File "./now.py", line 9, in traverse
for item,val in d.iteritems():
AttributeError: 'unicode' object has no attribute 'iteritems'
我知道我的第一个iteritems 电话是在错误的地方,但我就是想不通递归...任何指针表示赞赏。顺便说一句,我正在使用 Python 2。
编辑
我尝试处理的实际 json 比上面列出的更复杂。这是一个经过编辑的版本:
{
"install": {
"site": {
"acls": {
"dns": {
"authorized_ports": ["53:tcp", "53:udp"]
}
},
"network": {
"clusters": {
"__ip_range_1__": {
"dhcpstart": "__ip__",
"dhcpend": "__ip__",
"adminip": "__ip__"
},
"__ip_range_2__": {
"dhcpstart": "__ip__",
"dhcpend": "__ip__",
"adminip": "__ip__"
}
}
}
}
}
"config": {
"ippool": [
{
"pool_name": "/ippool1",
"pool_description": "IP Pool1",
"ranges": [["__ip__", "__ip__"]]
},
{
"pool_name": "/ippool2",
"pool_description": "IP Pool2",
"ranges": [["__ip__", "__ip__"]]
}
],
"storage": [
{
"account": "/root",
"credentials": {
"account": "admin",
"service": "storage",
"user": "admin",
"password": "pass"
}
}
]
}
}
我修改了 Paul Panzer 的答案以包括如下列表:
def traverse(d, path=[]):
for k, v in d.iteritems():
yield path + [k], v
if isinstance(v, dict):
for k,v in traverse(v, path + [k]):
yield k,v
elif isinstance(v, list):
for k in v:
traverse(k, path + [])
但是上面的内容并没有打印 ippool 和 storage 列表中的元素。一旦遇到字典列表,由于某种原因不会对其进行遍历。
【问题讨论】:
-
Keys (
item) 不能是lists 或dicts,所以你的第一个条件是没用的。当val是dict时,您假设v是dict,而不是True,因此您的错误。当val是dict时,您应该只递归traverse(val),而不是遍历val -
所以你的 test.json 在顶层只有一个键('install')。您的 __ip_range_x 的“路径”是否始终相同?例如总是在“安装”>“站点”>“网络”>“集群”中?
-
@MaxPower 我的 test.json 顶部有许多条目,一些 dict,一些 dict 的 dict 和更复杂的包括许多级别的 dict 和列表。但是,__ip_range_x 的路径始终相同。
-
好的,那么,AChampion 的回答对你有用吗?
-
@MaxPower 它产生太多的值来解压错误。
标签: python json recursion python-2.x