Python解析返回JSON:优雅处理字段缺失与默认值设置
解决JSON嵌套字段缺失的Pythonic方案
问题分析
你当前的代码直接通过键索引访问嵌套JSON字段,一旦某个字段缺失或列表为空,就会抛出KeyError或IndexError;而外层宽泛的except: continue会吞掉所有异常,不利于排查问题(比如JSON解析失败也会被直接跳过)。
方案一:使用dict.get()逐层兜底
这是标准库原生的方法,通过get()为每一层缺失的字段设置默认值,避免抛出异常:
import json try: data = response.read() json_response = json.loads(data) # 注:原代码中`json.loads(source)`应为`json.loads(data)`,属于笔误 # 逐层获取,为空时返回默认空字典/空列表 profiles = json_response.get('profiles', []) content = profiles[0].get('content', {}) if len(profiles) > 0 else {} # 为所有字段统一设置默认值(比如空字符串) name = content.get('nameFull', '') name_dict = content.get('name', {}) first_name = name_dict.get('first', '') surname = name_dict.get('last', '') employee_type_dict = content.get('employeeType', {}) employment_type = employee_type_dict.get('title', '') # 后续使用变量执行操作 except json.JSONDecodeError: # 只捕获JSON解析错误,其他异常(如网络错误)可单独处理 continue except (IndexError, KeyError): # 捕获字段缺失或列表为空的情况 continue
方案二:自定义嵌套取值函数(推荐)
通过functools.reduce封装一个通用的嵌套取值函数,一次性处理所有层级的缺失问题,还能统一设置默认值:
import json from functools import reduce def get_nested(data, key_chain, default=''): """安全获取嵌套结构的值,支持字典键和列表索引""" try: return reduce(lambda d, k: d[k], key_chain, data) except (KeyError, IndexError, TypeError): # KeyError:键不存在;IndexError:列表索引越界;TypeError:遇到非可索引对象 return default try: data = response.read() json_response = json.loads(data) # 用键链一次性取值,统一使用默认空字符串 name = get_nested(json_response, ['profiles', 0, 'content', 'nameFull']) first_name = get_nested(json_response, ['profiles', 0, 'content', 'name', 'first']) surname = get_nested(json_response, ['profiles', 0, 'content', 'name', 'last']) employment_type = get_nested(json_response, ['profiles', 0, 'content', 'employeeType', 'title']) # 后续操作 except json.JSONDecodeError: continue
这个函数的优势是代码更简洁,所有字段的默认值可以通过default参数统一设置(比如改成None或其他默认值),无需逐个字段指定。
方案三:第三方库glom(进阶)
如果可以引入第三方库,glom专门针对嵌套数据的取值和处理,语法更直观,支持批量设置默认值:
先安装库:pip install glom
import json from glom import glom, Coalesce try: data = response.read() json_response = json.loads(data) # 定义字段的取值路径 field_specs = { 'name': ('profiles', 0, 'content', 'nameFull'), 'first_name': ('profiles', 0, 'content', 'name', 'first'), 'surname': ('profiles', 0, 'content', 'name', 'last'), 'employment_type': ('profiles', 0, 'content', 'employeeType', 'title') } # 用Coalesce统一设置默认值为空字符串 result = glom(json_response, {k: Coalesce(v, '') for k, v in field_specs.items()}) # 提取变量 name = result['name'] first_name = result['first_name'] surname = result['surname'] employment_type = result['employment_type'] # 后续操作 except json.JSONDecodeError: continue
注意事项
- 避免使用
except:捕获所有异常,应该针对性捕获json.JSONDecodeError、KeyError、IndexError等明确的异常,防止忽略其他严重错误(如网络连接失败)。 - 原代码中
json.loads(source)应为json.loads(data),属于笔误,需要修正。
内容的提问来源于stack exchange,提问作者user14637930
相关产品推荐
相关产品推荐

