如何用Python优化JSON数组中按Key取值的代码(替代多IF)
优化Admin Reports数据提取的Python实现方案
问题背景
你有Google Admin Reports格式的JSON使用报告数据,需要提取指定name字段对应的各类*Value值。当前通过多个if语句匹配字段名的方式实现,代码冗余且不易维护,希望得到更简洁的优化方案。
原始JSON数据示例
{ "kind": "admin#reports#usageReport", "date": "2022-07-17", "etag": "\"dng2uCItaXPqmMj2MG4RUqVkRjnE_4kf0VvQ0_WkiTg/dICFK4HeNet7m-jGyh4UpD7jLI4\"", "entity": { "type": "USER", "customerId": "H01234sux", "userEmail": "harry.potter@hogwarts.edu", "profileId": "123456789999012345678" }, "parameters": [ { "name": "gmail:last_access_time", "datetimeValue": "2022-07-08T00:06:16.000Z" }, { "name": "gmail:num_emails_exchanged", "intValue": "0" }, { "name": "accounts:first_name", "stringValue": "Harry" }, { "name": "accounts:last_name", "stringValue": "Potter" }, { "name": "accounts:is_disabled", "boolValue": false }, { "name": "accounts:disabled_reason" }, { "name": "accounts:creation_time", "datetimeValue": "2022-05-26T21:54:18.000Z" }, { "name": "accounts:last_login_time", "datetimeValue": "1970-01-01T00:00:00.000Z" }, { "name": "accounts:is_super_admin", "boolValue": false }, { "name": "accounts:is_delegated_admin", "boolValue": false }, { "name": "accounts:drive_used_quota_in_mb", "intValue": "0" } ] }
原始实现代码
for user in users: uemail = user['entity']['userEmail']; for param in user['parameters']: if param['name'] == 'gmail:last_webmail_time': lwmtm = param['datetimeValue']; if param['name'] == 'accounts:total_quota_in_mb': ttlqmb = param['intValue'] if param['name'] == 'accounts:used_quota_in_mb': usqmb = param['intValue'] print(u'{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}'.format(uemail,lwmtm,lintm,lactm,acdstr,accrtm,aclltm,aclstm,drusmb,gmusmb,gpusmb,ttlqmb,usqmb))
优化实现方案
方案1:将参数列表转为字典(基础版)
核心思路是把每个用户的parameters列表转换为以name为键、对应*Value为值的字典,后续直接通过键名取值,彻底替代多if判断:
for user in users: uemail = user['entity']['userEmail'] # 构建参数字典:自动匹配所有带Value后缀的字段值 param_dict = {} for param in user['parameters']: # 提取参数中的值(兼容datetime/int/string/bool等类型) value = next((v for k, v in param.items() if k.endswith('Value')), None) param_dict[param['name']] = value # 通过get方法获取参数,可设置默认值避免KeyError或变量未定义 lwmtm = param_dict.get('gmail:last_webmail_time', '') ttlqmb = param_dict.get('accounts:total_quota_in_mb', '0') usqmb = param_dict.get('accounts:used_quota_in_mb', '0') # 补充其他需要提取的参数,示例: lintm = param_dict.get('xxx:xxx_field', '') lactm = param_dict.get('yyy:yyy_field', '') acdstr = param_dict.get('accounts:disabled_reason', '') accrtm = param_dict.get('accounts:creation_time', '') aclltm = param_dict.get('accounts:last_login_time', '') aclstm = param_dict.get('accounts:is_super_admin', False) drusmb = param_dict.get('accounts:drive_used_quota_in_mb', '0') gmusmb = param_dict.get('gmail:num_emails_exchanged', '0') gpusmb = param_dict.get('xxx:other_gmail_param', '') # 格式化输出(使用f-string更简洁) print(f"{uemail}, {lwmtm}, {lintm}, {lactm}, {acdstr}, {accrtm}, {aclltm}, {aclstm}, {drusmb}, {gmusmb}, {gpusmb}, {ttlqmb}, {usqmb}")
方案2:预定义参数映射(进阶版)
如果需要提取的参数固定,可以预先定义参数列表和默认值,批量处理提取逻辑,进一步提升可维护性:
# 预定义需要提取的参数:键为参数name,值为默认值 REQUIRED_PARAMS = { 'gmail:last_webmail_time': '', 'accounts:total_quota_in_mb': '0', 'accounts:used_quota_in_mb': '0', 'xxx:xxx_field': '', 'yyy:yyy_field': '', 'accounts:disabled_reason': '', 'accounts:creation_time': '', 'accounts:last_login_time': '', 'accounts:is_super_admin': False, 'accounts:drive_used_quota_in_mb': '0', 'gmail:num_emails_exchanged': '0', 'xxx:other_gmail_param': '' } for user in users: uemail = user['entity']['userEmail'] # 构建参数字典 param_dict = { p['name']: next((v for k, v in p.items() if k.endswith('Value')), None) for p in user['parameters'] } # 合并默认值与实际提取的值 extracted_params = {k: param_dict.get(k, v) for k, v in REQUIRED_PARAMS.items()} # 按顺序组装输出内容 output_values = [uemail] + list(extracted_params.values()) print(', '.join(map(str, output_values)))
方案优势
- 简洁性:消除大量重复的
if判断,代码结构更清晰 - 健壮性:通过
get方法设置默认值,避免因参数缺失导致的KeyError或变量未定义问题 - 可维护性:后续新增或修改提取参数时,只需调整字典配置,无需修改循环逻辑
内容的提问来源于stack exchange,提问作者Venkat5121
相关产品推荐
相关产品推荐

