如何在Python中处理API响应中缺失的JSON嵌套键?
解决嵌套字典中None值的键访问报错问题
问题场景
API返回的JSON响应中,部分字段可能为None,例如:
{ "associates": [ { "name":"DOE", "fname":"John", "direct_shares":50, "direct_shares_details":{ "shares_PP":25, "shares_NP":25 }, "indirect_shares":None, "indirect_shares_details": None } ] }
当尝试访问indirect_shares_details下的嵌套键(如first_type)时,会因该字段为None触发报错。现有处理函数存在此问题:
def get_shares_data(response): associate_from_api = [] for i in response["associates"]: associate_data = { "PM_shares": round(company["Shares"], 2), "full_name": i["name"] + " " + i["fname"], "details": { "shares_in_PM": i["direct_shares"], "shares_PP_in_PM": i["direct_shares_details"]["shares_PP"], "shares_NP_in_PM": i["direct_shares_details"]["shares_NP"], "shares_directe": i["indirect_shares"], "shares_indir_PP_1": i["indirect_shares_details"]["first_type"]["shares_PP"], "shares_indir_NP_1": i["indirect_shares_details"]["first_type"]["shares_NP"], "shares_indir_PP_2": i["indirect_shares_details"]["second_type"]["shares_PP"], "shares_indir_NP_2": i["indirect_shares_details"]["second_type"]["shares_NP"], } } for key,value in associate_data["details"].items(): if value != None: associate_data["details"][key] = value * associate_data["PM_shares"] / 100 else: associate_data["calculs"][key] = 0.0 associate_from_api.append(associate_data) return associate_from_api
高效解决方法
方法1:使用字典get()方法链式调用
利用字典的get()方法,为每一层嵌套设置默认值,避免直接访问报错。若某一层为None,则返回预设的空字典,再继续处理:
def get_shares_data(response): associate_from_api = [] pm_shares = round(company["Shares"], 2) for i in response["associates"]: # 安全获取间接持股详情,若为None则返回空字典 indirect_details = i.get("indirect_shares_details", {}) or {} first_type = indirect_details.get("first_type", {}) or {} second_type = indirect_details.get("second_type", {}) or {} associate_data = { "PM_shares": pm_shares, "full_name": f"{i['name']} {i['fname']}", "details": { "shares_in_PM": i["direct_shares"], "shares_PP_in_PM": i["direct_shares_details"]["shares_PP"], "shares_NP_in_PM": i["direct_shares_details"]["shares_NP"], "shares_directe": i.get("indirect_shares"), "shares_indir_PP_1": first_type.get("shares_PP"), "shares_indir_NP_1": first_type.get("shares_NP"), "shares_indir_PP_2": second_type.get("shares_PP"), "shares_indir_NP_2": second_type.get("shares_NP"), } } # 统一处理数值计算,修正原函数未定义的calculs字段问题 for key, value in associate_data["details"].items(): if value is not None: associate_data["details"][key] = round(value * pm_shares / 100, 2) else: associate_data["details"][key] = 0.0 associate_from_api.append(associate_data) return associate_from_api
方法2:编写通用安全取值函数
如果嵌套层级较多,可编写一个通用函数来安全获取多层嵌套的值,简化代码:
def safe_get(data, keys, default=None): """安全获取多层嵌套字典的值""" for key in keys: if data is None or not isinstance(data, dict): return default data = data.get(key, default) return data def get_shares_data(response): associate_from_api = [] pm_shares = round(company["Shares"], 2) for i in response["associates"]: associate_data = { "PM_shares": pm_shares, "full_name": f"{i['name']} {i['fname']}", "details": { "shares_in_PM": i["direct_shares"], "shares_PP_in_PM": i["direct_shares_details"]["shares_PP"], "shares_NP_in_PM": i["direct_shares_details"]["shares_NP"], "shares_directe": i.get("indirect_shares"), "shares_indir_PP_1": safe_get(i, ["indirect_shares_details", "first_type", "shares_PP"]), "shares_indir_NP_1": safe_get(i, ["indirect_shares_details", "first_type", "shares_NP"]), "shares_indir_PP_2": safe_get(i, ["indirect_shares_details", "second_type", "shares_PP"]), "shares_indir_NP_2": safe_get(i, ["indirect_shares_details", "second_type", "shares_NP"]), } } for key, value in associate_data["details"].items(): if value is not None: associate_data["details"][key] = round(value * pm_shares / 100, 2) else: associate_data["details"][key] = 0.0 associate_from_api.append(associate_data) return associate_from_api
关键修正点
- 处理
indirect_shares_details为None的情况,通过get()或安全函数返回默认值,避免直接访问嵌套键报错 - 修正原函数中
associate_data["calculs"]未定义的错误,统一将计算后的值写入details字典 - 使用
f-string优化全名拼接,代码更简洁 - 增加
round()保留小数位数,保证数值精度
内容的提问来源于stack exchange,提问作者user16779293
相关产品推荐
相关产品推荐

