在 Python 中通过嵌套的 Json/dict 解析
Posted
技术标签:
【中文标题】在 Python 中通过嵌套的 Json/dict 解析【英文标题】:Parsing through Nested Json/dict in Python 【发布时间】:2021-05-15 20:00:05 【问题描述】:处理一些讨厌的 JSON。我正在使用 json.load 写入文件并将其存储为 dict 类型,打印在下面。在 python 中,我将如何获取仅在“false_value”之后开始的“维度”值的列表(因为它们的第一个维度值实际上不是我想要的值)。
我尝试了一种 hacky 方式,但感觉有人可能对如何以更有说服力的方式做到这一点有看法。
目标,列出所有维度值(除第一个之外),例如 ('100', '121' ...)
"reports": [
"columnHeader":
"dimensions": [
"ga:clientId"
],
"metricHeader":
"metricHeaderEntries": [
"name": "blah",
"type": "INTEGER"
]
,
"data":
"rows": [
"dimensions": [
"false_value"
],
"metrics": [
"values": [
"2"
]
]
,
"dimensions": [
"100"
],
"metrics": [
"values": [
"2"
]
]
,
"dimensions": [
"121"
],
"metrics": [
"values": [
"1"
]
]
,
"dimensions": [
"1212"
],
"metrics": [
"values": [
"1"
]
]
, ],
"totals": [
"values": [
"10497"
]
],
"rowCount": 9028,
"minimums": [
"values": [
"0"
]
],
"maximums": [
"values": [
"9"
]
],
"isDataGolden": true
,
"nextPageToken": "1000"
]
【问题讨论】:
我相信您可以遍历所有键/子键/值并将它们转储到列表中。见这里:***.com/questions/45974937 您的意思是 True 而不是 true(即 Python Boolean 的 True/False)? @DarrylG 这是 JSON,不是 Python 代码。 一个在条件中使用isinstance()
的简单递归函数应该可以解决问题。
@DannyVarod--当 OP 说“它存储的是 dict 类型,打印在下面”时,我假设 OP 显示为字典。如果我们将其视为字符串,那么 json.loads(...) 会给出结构错误(这也是由字符串的 json lint 验证器引发的)。如果将 true 更改为 True,则它可以作为字典使用。
【参考方案1】:
首先,你应该把你的 json 对象放在一个更好的文本可读形式。使用Black 之类的东西来清理空间。 然后只需遍历键,直到找到所需的值,此 post 将帮助您。
你应该得到这样的结果:
dimensions = [row["dimensions"][0] for row in json["reports"][0]["data"]["rows"]]
【讨论】:
非常酷和整洁,非常喜欢。关于如何忽略第一个值的任何提示? 查看这篇文章:How to remove the first item in a list【参考方案2】:使用递归函数查找具有两个条件的值
父键是维度 只取数值代码
def find_dims(d, inside = False, results = None):
'''
Recursive processing of structure
inside = True when parent was "dimensions"
'''
if results is None:
results = []
if isinstance(d, dict):
for k, v in d.items():
find_dims(v, k=="dimensions" or inside, results)
elif isinstance(d, list):
for k in d:
find_dims(k, inside, results)
else:
if inside and d.isdigit():
# inside dimensions with a number
results.append(int(d))
return results
测试
OP 字典(将 true 更改为 True)
d =
"reports": [
"columnHeader":
"dimensions": [
"ga:clientId"
],
"metricHeader":
"metricHeaderEntries": [
"name": "blah",
"type": "INTEGER"
]
,
"data":
"rows": [
"dimensions": [
"false_value"
],
"metrics": [
"values": [
"2"
]
]
,
"dimensions": [
"100"
],
"metrics": [
"values": [
"2"
]
]
,
"dimensions": [
"121"
],
"metrics": [
"values": [
"1"
]
]
,
"dimensions": [
"1212"
],
"metrics": [
"values": [
"1"
]
]
, ],
"totals": [
"values": [
"10497"
]
],
"rowCount": 9028,
"minimums": [
"values": [
"0"
]
],
"maximums": [
"values": [
"9"
]
],
"isDataGolden": True
,
"nextPageToken": "1000"
]
print(find_dims(d)) # Output: [100, 121, 1212]
【讨论】:
【参考方案3】:就像 cmets 中所说的,你可以只使用一个简单的递归函数,例如:
all_dimensions = []
search_key = 'dimensions'
def searchDimensions(data):
if isinstance(data, dict):
for (key, sub_data) in data.items():
if key == search_key: all_dimensions.extend(sub_data)
else: all_dimensions.extend(searchDimensions(sub_data))
elif isinstance(data, list):
for sub_data in data:
all_dimensions.extend(searchDimensions(sub_data))
return []
searchDimensions(example)
false_value_index = all_dimensions.index('false_value') + 1
output = all_dimensions[false_value_index:]
print(output)
>>> ['100', '121', '1212']
然后过滤你不想要的值(例如,从false_value
开始)
【讨论】:
以上是关于在 Python 中通过嵌套的 Json/dict 解析的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Mysql 中通过 LIKE 使用嵌套的 SELECT?
如何使用存储库接口在 Spring Data 中通过其嵌套对象的 objectId 查找集合?
如何在 VUE 中通过 v-model 直接更新嵌套对象数组值?