[英]Python how to return a dictionary from a recursive function parsing a nested json?
I'm trying to parse a nested json file for a specific key value "Date" and return a dictionary that should look like我正在尝试为特定键值“Date”解析嵌套的 json 文件并返回一个看起来应该像这样的字典
{'Date', '2022-05-20T00:00:00Z'}
Here is my code:这是我的代码:
meetingDate_dict = {}
def recursive_json(data,attr,m_dict):
for k,v in data.items():
if k == attr:
for k2,v2 in v.items():
m_dict = {attr, v2}
print('IF: ',m_dict)
return m_dict
elif isinstance(v,dict):
print('ELIF: ', k,v)
return recursive_json(v,attr,m_dict)
else:
print('ELSE: ',k,v)
print('END')
print('RETURN: ',recursive_json(assessment_json, "Date", meetingDate_dict))
Output: Output:
ELSE: $id 1
ELIF: DataChangedEntry {'$id': '2', 'PathProperty': '/', 'Metadata': None, 'PreviousValue': None, 'CurrentValue': {'CosewicWsRefId': {'Value': 'QkNlrjq2HL9bhTQqU8-qH'}, 'Date': {'Value': '2022-05-20T00:00:00Z'}, 'YearSentToMinister': {'Value': '0001-01-01T00:00:00'}, 'DateSentToMinister': {'Value': '0001-01-01T00:00:00'}, 'Order': None, 'Type': {'Value': 'REGULAR'}, 'ReportType': {'Value': 'NEW'}, 'Stage': {'Value': 'ASSESSED'}, 'State': {'Value': 'PUBLISHED'}, 'StatusAndCriteria': {'Status': {'Value': 'EXTINCT'}, 'StatusComment': {'EnglishText': None, 'FrenchText': None}, 'StatusChange': {'Value': 'NOT_INITIALIZED'}, 'StatusCriteria': {'EnglishText': None, 'FrenchText': None}, 'ApplicabilityOfCriteria': {'ApplicabilityCriteriaList': []}}, 'Designation': None, 'Note': None, 'DomainEvents': [], 'Version': {'Value': 1651756761385.1248}, 'Id': {'Value': '3z3XlCkaXY9xinAbK5PrU'}, 'CreatedAt': {'Value': 1651756761384}, 'ModifiedAt': {'Value': 1651756785274}, 'CreatedBy': {'Value': 'Geordie.Powers@ec.gc.ca'}, 'ModifiedBy': {'Value': 'Geordie.Powers@ec.gc.ca'}}}
ELSE: $id 2
ELSE: PathProperty /
ELSE: Metadata None
ELSE: PreviousValue None
ELIF: CurrentValue {'CosewicWsRefId': {'Value': 'QkNlrjq2HL9bhTQqU8-qH'}, 'Date': {'Value': '2022-05-20T00:00:00Z'}, 'YearSentToMinister': {'Value': '0001-01-01T00:00:00'}, 'DateSentToMinister': {'Value': '0001-01-01T00:00:00'}, 'Order': None, 'Type': {'Value': 'REGULAR'}, 'ReportType': {'Value': 'NEW'}, 'Stage': {'Value': 'ASSESSED'}, 'State': {'Value': 'PUBLISHED'}, 'StatusAndCriteria': {'Status': {'Value': 'EXTINCT'}, 'StatusComment': {'EnglishText': None, 'FrenchText': None}, 'StatusChange': {'Value': 'NOT_INITIALIZED'}, 'StatusCriteria': {'EnglishText': None, 'FrenchText': None}, 'ApplicabilityOfCriteria': {'ApplicabilityCriteriaList': []}}, 'Designation': None, 'Note': None, 'DomainEvents': [], 'Version': {'Value': 1651756761385.1248}, 'Id': {'Value': '3z3XlCkaXY9xinAbK5PrU'}, 'CreatedAt': {'Value': 1651756761384}, 'ModifiedAt': {'Value': 1651756785274}, 'CreatedBy': {'Value': 'Geordie.Powers@ec.gc.ca'}, 'ModifiedBy': {'Value': 'Geordie.Powers@ec.gc.ca'}}
ELIF: CosewicWsRefId {'Value': 'QkNlrjq2HL9bhTQqU8-qH'}
ELSE: Value QkNlrjq2HL9bhTQqU8-qH
END
RETURN: None
So this way doesn't ever print the correct key:value pair, and returns None.所以这种方式永远不会打印出正确的键值对,并返回 None。 If I remove the
return
statement in the elif
I at least get the correct print out from the if
statement, but I still get None
returned:如果我删除了
elif
中的return
语句,我至少从if
语句中得到了正确的打印,但我仍然没有返回None
:
meetingDate_dict = {}
def recursive_json(data,attr,m_dict):
for k,v in data.items():
if k == attr:
for k2,v2 in v.items():
m_dict = {attr, v2}
print('IF: ',m_dict)
return m_dict
elif isinstance(v,dict):
print('ELIF: ', k,v)
recursive_json(v,attr,m_dict)
else:
print('ELSE: ',k,v)
print('END')
print('RETURN: ',recursive_json(assessment_json, "Date", meetingDate_dict))
Output: Output:
ELSE: $id 1
ELIF: DataChangedEntry {'$id': '2', 'PathProperty': '/', 'Metadata': None, 'PreviousValue': None, 'CurrentValue': {'CosewicWsRefId': {'Value': 'QkNlrjq2HL9bhTQqU8-qH'}, 'Date': {'Value': '2022-05-20T00:00:00Z'}, 'YearSentToMinister': {'Value': '0001-01-01T00:00:00'}, 'DateSentToMinister': {'Value': '0001-01-01T00:00:00'}, 'Order': None, 'Type': {'Value': 'REGULAR'}, 'ReportType': {'Value': 'NEW'}, 'Stage': {'Value': 'ASSESSED'}, 'State': {'Value': 'PUBLISHED'}, 'StatusAndCriteria': {'Status': {'Value': 'EXTINCT'}, 'StatusComment': {'EnglishText': None, 'FrenchText': None}, 'StatusChange': {'Value': 'NOT_INITIALIZED'}, 'StatusCriteria': {'EnglishText': None, 'FrenchText': None}, 'ApplicabilityOfCriteria': {'ApplicabilityCriteriaList': []}}, 'Designation': None, 'Note': None, 'DomainEvents': [], 'Version': {'Value': 1651756761385.1248}, 'Id': {'Value': '3z3XlCkaXY9xinAbK5PrU'}, 'CreatedAt': {'Value': 1651756761384}, 'ModifiedAt': {'Value': 1651756785274}, 'CreatedBy': {'Value': 'Geordie.Powers@ec.gc.ca'}, 'ModifiedBy': {'Value': 'Geordie.Powers@ec.gc.ca'}}}
ELSE: $id 2
ELSE: PathProperty /
ELSE: Metadata None
ELSE: PreviousValue None
ELIF: CurrentValue {'CosewicWsRefId': {'Value': 'QkNlrjq2HL9bhTQqU8-qH'}, 'Date': {'Value': '2022-05-20T00:00:00Z'}, 'YearSentToMinister': {'Value': '0001-01-01T00:00:00'}, 'DateSentToMinister': {'Value': '0001-01-01T00:00:00'}, 'Order': None, 'Type': {'Value': 'REGULAR'}, 'ReportType': {'Value': 'NEW'}, 'Stage': {'Value': 'ASSESSED'}, 'State': {'Value': 'PUBLISHED'}, 'StatusAndCriteria': {'Status': {'Value': 'EXTINCT'}, 'StatusComment': {'EnglishText': None, 'FrenchText': None}, 'StatusChange': {'Value': 'NOT_INITIALIZED'}, 'StatusCriteria': {'EnglishText': None, 'FrenchText': None}, 'ApplicabilityOfCriteria': {'ApplicabilityCriteriaList': []}}, 'Designation': None, 'Note': None, 'DomainEvents': [], 'Version': {'Value': 1651756761385.1248}, 'Id': {'Value': '3z3XlCkaXY9xinAbK5PrU'}, 'CreatedAt': {'Value': 1651756761384}, 'ModifiedAt': {'Value': 1651756785274}, 'CreatedBy': {'Value': 'Geordie.Powers@ec.gc.ca'}, 'ModifiedBy': {'Value': 'Geordie.Powers@ec.gc.ca'}}
ELIF: CosewicWsRefId {'Value': 'QkNlrjq2HL9bhTQqU8-qH'}
ELSE: Value QkNlrjq2HL9bhTQqU8-qH
END
IF: {'Date', '2022-05-20T00:00:00Z'}
END
ELSE: EventAction Create
ELIF: EventDataChange {'$ref': '2'}
ELSE: $ref 2
END
ELSE: CorrelationId 3z3XlCkaXY9xinAbK5PrU
ELSE: EventId WGxlewsUAHayLHZ2LHvFk
ELSE: EventTimeUtc 2022-05-06T13:15:31.7463355Z
ELSE: EventDataVersion 1.0.0
ELSE: EventType AssessmentCreatedInfrastructure
END
RETURN: None
The json file: json 文件:
{
"$id": "1",
"DataChangedEntry": {
"$id": "2",
"PathProperty": "/",
"Metadata": null,
"PreviousValue": null,
"CurrentValue": {
"CosewicWsRefId": {
"Value": "QkNlrjq2HL9bhTQqU8-qH"
},
"Date": {
"Value": "2022-05-20T00:00:00Z"
},
"YearSentToMinister": {
"Value": "0001-01-01T00:00:00"
},
"DateSentToMinister": {
"Value": "0001-01-01T00:00:00"
},
"Order": null,
"Type": {
"Value": "REGULAR"
},
"ReportType": {
"Value": "NEW"
},
"Stage": {
"Value": "ASSESSED"
},
"State": {
"Value": "PUBLISHED"
},
"StatusAndCriteria": {
"Status": {
"Value": "EXTINCT"
},
"StatusComment": {
"EnglishText": null,
"FrenchText": null
},
"StatusChange": {
"Value": "NOT_INITIALIZED"
},
"StatusCriteria": {
"EnglishText": null,
"FrenchText": null
},
"ApplicabilityOfCriteria": {
"ApplicabilityCriteriaList": []
}
},
"Designation": null,
"Note": null,
"DomainEvents": [],
"Version": {
"Value": 1651756761385.1248
},
"Id": {
"Value": "3z3XlCkaXY9xinAbK5PrU"
},
"CreatedAt": {
"Value": 1651756761384
},
"ModifiedAt": {
"Value": 1651756785274
},
"CreatedBy": {
"Value": "a@a"
},
"ModifiedBy": {
"Value": "a@a"
}
}
},
"EventAction": "Create",
"EventDataChange": {
"$ref": "2"
},
"CorrelationId": "3z3XlCkaXY9xinAbK5PrU",
"EventId": "WGxlewsUAHayLHZ2LHvFk",
"EventTimeUtc": "2022-05-06T13:15:31.7463355Z",
"EventDataVersion": "1.0.0",
"EventType": "AssessmentCreatedInfrastructure"
}
I think the problem here is because when looking for attr
in deeper levels, you didn't check whether recursive_json(v,attr,m_dict)
is returning the actual desired value or None
and just return it anyway.我认为这里的问题是因为在更深层次上寻找
attr
时,您没有检查recursive_json(v,attr,m_dict)
是否返回实际所需的值或None
并且无论如何都返回它。 Changing the code to:将代码更改为:
def recursive_json(data,attr,m_dict):
...
# find attr value in deeper levels
elif isinstance(v,dict):
result = recursive_json(v,attr,m_dict)
# if result is not None, return it
if result:
return result
...
I would refactor your recursive_json
function as follows, removing m_dict
as it seems unnecessary:我会重构你的
recursive_json
function 如下,删除m_dict
似乎没有必要:
def recursive_json(data: dict, lookup_key: str, value_key: str = "Value"):
# look for all key-value pairs at current levels
for k, v in data.items():
# Check if current pair satisfies the following conditions:
# - key equal to lookup key
# - value is a dictionary
# - value dictionary has subkey named `Value`
if k == lookup_key and isinstance(v, dict) and value_key in v:
return {lookup_key: v.get(value_key)}
# else if value is a dictionary, search `lookup_key` in deeper levels
elif isinstance(v, dict):
lookup_result = recursive_json(v, lookup_key, value_key)
# if value for `lookup_key` is found in deeper levels, return the value
if lookup_result:
return lookup_result
# return None as no satisfied value found
return None
Edit: For multiple instances of lookup_key
, try the following method:编辑:对于
lookup_key
的多个实例,请尝试以下方法:
def recursive_json(data: dict, lookup_keys: list, value_key: str = "Value"):
if isinstance(lookup_keys, str):
lookup_keys = [lookup_keys]
# BFS
search_q = [data]
# look for all key-value pairs at current levels
lookup_result = {}
while search_q and lookup_keys:
in_search_dict = search_q.pop(0)
for k, v in in_search_dict.items():
# Check if current pair satisfies the following conditions:
# - key equal to lookup key
# - value is a dictionary
# - value dictionary has subkey named `Value`
if isinstance(v, dict):
if value_key in v and k in lookup_keys:
# remove `value_key` from current dict
value = v.pop(value_key)
# update lookup result
lookup_result.update({k: value})
# remove found key from lookup keys
lookup_keys.remove(k)
# if all lookup keys are found, break the while loop
if not lookup_keys:
break
if v:
search_q.append(v)
# return lookup result
return lookup_result
print(recursive_json(assessment_json, ["Date", "ModifiedBy", "CreatedBy"]))
# {'Date': '2022-05-20T00:00:00Z', 'CreatedBy': 'a@a', 'ModifiedBy': 'a@a'}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.