如何无需外部递归函数解析多层嵌套JSON键?Discord Bot开发求助
如何提取Discord Bot API响应中的嵌套JSON字段值
我明白你现在遇到的问题了——你想从API返回的嵌套JSON数据里提取current、today、day30这些键下的trend值,但之前的解析方式走了弯路,导致拿不到结果。让我帮你理清楚问题所在,然后给出直接有效的解决方案。
问题出在哪?
你之前的代码犯了两个关键错误:
- 没必要把字典转成字符串再解析:
val['current']本身就是Python的字典类型,你却把它转成字符串后再用json.loads()去解析,这不仅多此一举,还会因为字符串里的单引号不符合JSON标准(JSON要求双引号)而导致解析失败。 - 判断键存在的方式错误:你用了
'trend' in parse_current_vals.items(),但items()返回的是键值对的元组列表,正确的判断方式应该是直接检查'trend' in parse_current_vals。
直接有效的解决方案
既然val['current']、val['today']这些都是字典,你可以直接通过键名访问它们的子字段,根本不需要额外的字符串转JSON操作。
基础修正版代码
先看针对单个字段的修正:
get_item_data = requests.get(item_endpoint).json() for key, val in get_item_data.items(): if(query_id == str(val['id'])): # 提取描述 if 'description' in val: await context.send(val['description']) # 提取current的trend和price if 'current' in val: current_data = val['current'] if 'trend' in current_data: await context.send(f"当前趋势: {current_data['trend']}") if 'price' in current_data: await context.send(f"当前价格: {current_data['price']}") # 提取today的trend和price变化 if 'today' in val: today_data = val['today'] if 'trend' in today_data: await context.send(f"今日趋势: {today_data['trend']}") if 'price' in today_data: await context.send(f"今日价格变化: {today_data['price']}") # 提取day30/day90/day180的trend和变化率 for period in ['day30', 'day90', 'day180']: if period in val: period_data = val[period] if 'trend' in period_data: await context.send(f"{period}趋势: {period_data['trend']}") if 'change' in period_data: await context.send(f"{period}变化率: {period_data['change']}") break
更简洁的优化版
如果你想减少重复代码,可以把需要处理的嵌套键整理成列表,循环处理:
get_item_data = requests.get(item_endpoint).json() # 定义需要处理的嵌套键及其对应的字段和展示文本 target_fields = [ ('current', ['trend', 'price'], '当前'), ('today', ['trend', 'price'], '今日'), ('day30', ['trend', 'change'], '30天'), ('day90', ['trend', 'change'], '90天'), ('day180', ['trend', 'change'], '180天'), ] for key, val in get_item_data.items(): if(query_id == str(val['id'])): # 先发送描述 if 'description' in val: await context.send(val['description']) # 循环处理所有目标嵌套字段 for field_name, sub_fields, display_name in target_fields: if field_name in val: data = val[field_name] msg_parts = [] for sub_field in sub_fields: if sub_field in data: if sub_field == 'trend': msg_parts.append(f"{display_name}趋势: {data[sub_field]}") elif sub_field == 'price': msg_parts.append(f"价格: {data[sub_field]}") elif sub_field == 'change': msg_parts.append(f"变化率: {data[sub_field]}") if msg_parts: await context.send(' | '.join(msg_parts)) break
这样代码更简洁,后续如果需要添加新的时间周期,只需要在target_fields里加一行就行。
测试后的预期输出
用你提供的JSON数据测试,优化版代码会输出:
Example Item Description 当前趋势: neutral | 价格: 1,210 今日趋势: negative | 价格: - 16 30天趋势: negative | 变化率: -4.0% 90天趋势: negative | 变化率: -8.0% 180天趋势: negative | 变化率: -3.0%
内容的提问来源于stack exchange,提问作者D7L6-D6L7
相关产品推荐
相关产品推荐

