递归枚举 JSON 层次结构 parent/child 到字典
Recursive enumerate JSON hierarchy parent/child to dictionary
我希望将未知结构的 JSON 层次结构扁平化为字典,捕获字典结果中的完整键层次结构以唯一标识它。
到目前为止,我能够递归地为所有 parent/child 节点打印 key:value 对,但我遇到了问题:
(1) 弄清楚如何为递归(子)执行传递父层次结构键,然后在退出子键时重置它。
(2) 写入单个字典结果 - 当我在递归函数中定义字典时,我最终创建了多个字典......我是否需要将此函数包装在主函数中以避免这种情况?
谢谢!
# flatten/enumerate example I'm using
with open('_json\file.json') as f:
data = json.load(f)
def parse_json_response(content):
if len (content.keys()) > 1 :
for key, value in content.items():
if type(value) is dict:
parse_json_response(value)
else:
print('{}:{}'.format(key,value))
else:
print(value)
if __name__ == '__main__':
parse_json_response(data)
# current result as print
id = 12345
firstName = John
lastName = Smith
DOB = 1980-01-01
phone = 123
line1 = Unit 4
line2 = 3 Main st
# desired result to dictionary {}
id = 12345
fields.firstName = John
fields.lastName = Smith
fields.DOB = 1980-01-01
fields.phone = 123
fields.address.residential.line1 = Unit 4
fields.address.residential.line2 = 3 Main st
试试下面这个:
test = {
"ID": "12345",
"fields": {
"firstName": "John",
"lastName": "Smith",
"DOB": "1980-01-01",
"phoneLand": "610292659333",
"address": {
"residential": {
"line1": "Unit 4",
"line2": "3 Main st"
}
}
}
}
def func(d, parent=""):
for key, value in d.items():
if isinstance(value, dict):
func(value, parent=parent+key+".")
else:
print(f"{parent+key} = {value}")
func(test)
结果:
ID = 12345
fields.firstName = John
fields.lastName = Smith
fields.DOB = 1980-01-01
fields.phoneLand = 610292659333
fields.address.residential.line1 = Unit 4
fields.address.residential.line2 = 3 Main st
您可以通过跟踪父项并在正确的位置递归来创建扁平化字典(而不仅仅是打印值)。这可能看起来像:
d = {
"ID": "12345",
"fields": {
"firstName": "John",
"lastName": "Smith",
"DOB": "1980-01-01",
"phoneLand": "610292659333",
"address": {
"residential": {
"line1": "Unit 4",
"line2": "3 Main st"
}
}
}
}
def flattenDict(d, parent=None):
ret = {}
for k, v in d.items():
if parent:
k = f'{parent}.{k}'
if isinstance(v, dict):
ret.update(flattenDict(v, k))
else:
ret[k] = v
return ret
flat = flattenDict(d)
flat
将是:
{'ID': '12345',
'fields.firstName': 'John',
'fields.lastName': 'Smith',
'fields.DOB': '1980-01-01',
'fields.phoneLand': '610292659333',
'fields.address.residential.line1': 'Unit 4',
'fields.address.residential.line2': '3 Main st'}
您还可以将输出安排为生成元组的生成器。然后您可以将其传递给 dict()
以获得相同的结果:
def flattenDict(d):
for k, v in d.items():
if isinstance(v, dict):
yield from ((f'{k}.{kk}', v) for kk, v in flattenDict(v))
else:
yield (k, v)
dict(flattenDict(d))
我希望将未知结构的 JSON 层次结构扁平化为字典,捕获字典结果中的完整键层次结构以唯一标识它。
到目前为止,我能够递归地为所有 parent/child 节点打印 key:value 对,但我遇到了问题:
(1) 弄清楚如何为递归(子)执行传递父层次结构键,然后在退出子键时重置它。
(2) 写入单个字典结果 - 当我在递归函数中定义字典时,我最终创建了多个字典......我是否需要将此函数包装在主函数中以避免这种情况?
谢谢!
# flatten/enumerate example I'm using
with open('_json\file.json') as f:
data = json.load(f)
def parse_json_response(content):
if len (content.keys()) > 1 :
for key, value in content.items():
if type(value) is dict:
parse_json_response(value)
else:
print('{}:{}'.format(key,value))
else:
print(value)
if __name__ == '__main__':
parse_json_response(data)
# current result as print
id = 12345
firstName = John
lastName = Smith
DOB = 1980-01-01
phone = 123
line1 = Unit 4
line2 = 3 Main st
# desired result to dictionary {}
id = 12345
fields.firstName = John
fields.lastName = Smith
fields.DOB = 1980-01-01
fields.phone = 123
fields.address.residential.line1 = Unit 4
fields.address.residential.line2 = 3 Main st
试试下面这个:
test = {
"ID": "12345",
"fields": {
"firstName": "John",
"lastName": "Smith",
"DOB": "1980-01-01",
"phoneLand": "610292659333",
"address": {
"residential": {
"line1": "Unit 4",
"line2": "3 Main st"
}
}
}
}
def func(d, parent=""):
for key, value in d.items():
if isinstance(value, dict):
func(value, parent=parent+key+".")
else:
print(f"{parent+key} = {value}")
func(test)
结果:
ID = 12345
fields.firstName = John
fields.lastName = Smith
fields.DOB = 1980-01-01
fields.phoneLand = 610292659333
fields.address.residential.line1 = Unit 4
fields.address.residential.line2 = 3 Main st
您可以通过跟踪父项并在正确的位置递归来创建扁平化字典(而不仅仅是打印值)。这可能看起来像:
d = {
"ID": "12345",
"fields": {
"firstName": "John",
"lastName": "Smith",
"DOB": "1980-01-01",
"phoneLand": "610292659333",
"address": {
"residential": {
"line1": "Unit 4",
"line2": "3 Main st"
}
}
}
}
def flattenDict(d, parent=None):
ret = {}
for k, v in d.items():
if parent:
k = f'{parent}.{k}'
if isinstance(v, dict):
ret.update(flattenDict(v, k))
else:
ret[k] = v
return ret
flat = flattenDict(d)
flat
将是:
{'ID': '12345',
'fields.firstName': 'John',
'fields.lastName': 'Smith',
'fields.DOB': '1980-01-01',
'fields.phoneLand': '610292659333',
'fields.address.residential.line1': 'Unit 4',
'fields.address.residential.line2': '3 Main st'}
您还可以将输出安排为生成元组的生成器。然后您可以将其传递给 dict()
以获得相同的结果:
def flattenDict(d):
for k, v in d.items():
if isinstance(v, dict):
yield from ((f'{k}.{kk}', v) for kk, v in flattenDict(v))
else:
yield (k, v)
dict(flattenDict(d))