从S3获取JSON后,Alexa技能中Python字典访问报错求助
解决Alexa技能中Python字典属性访问的AttributeError问题
问题背景
使用Alexa自定义部署模板开发技能,具备Python开发经验但刚接触Alexa生态。为保留DynamoDB免费额度,选择从S3加载静态JSON数据。当前代码可成功获取并解析JSON(CloudWatch日志已显示解析结果),但尝试用test_json_data.test1访问数据时触发错误:
AttributeError: 'dict' object has no attribute 'test1'
怀疑是编码问题,但json.loads()未抛出解析错误。
错误原因
json.loads()将JSON字符串解析后返回的是Python字典类型,而非自定义类对象。字典的键值对必须通过[键名]的方式访问,点语法(对象.属性)仅适用于访问类实例的属性,因此直接用点访问字典会触发AttributeError。
从CloudWatch日志输出{'test1': 'test one output', ...}也能明确看出,解析结果是标准字典结构。
解决方案
1. 改用字典键访问语法
将点语法替换为方括号+字符串键的形式:
# 错误写法 print(test_json_data.test1) # 正确写法 print(test_json_data['test1'])
对于嵌套结构(如test3下的test4),需要结合列表索引和字典键访问:
# 访问test3列表中第一个字典的test4键 print(test_json_data['test3'][0]['test4'])
修改后的完整Handler示例
class HelloWorldIntentHandler(AbstractRequestHandler): """Handler for Hello World Intent.""" def can_handle(self, handler_input): return ask_utils.is_intent_name("HelloWorldIntent")(handler_input) def handle(self, handler_input): json_url = create_presigned_url("Media/json_data/test.json") test_raw_data = requests.get(json_url).content test_json_data = json.loads(test_raw_data) # 正确访问字典数据 test1_value = test_json_data['test1'] print(test1_value) # 嵌套数据访问示例 test4_value = test_json_data['test3'][0]['test4'] print(test4_value) speak_output = f"Hello World, test1的内容是{test1_value}" return ( handler_input.response_builder .speak(speak_output) # .ask("add a reprompt if you want to keep the session open for the user to respond") .response )
2. 可选:将字典转为对象(适配点语法)
如果习惯用点语法访问,可以通过types.SimpleNamespace将字典转为对象:
import types # 顶层字典转对象 test_json_obj = types.SimpleNamespace(**test_json_data) print(test_json_obj.test1) # 嵌套列表中的字典也需要转换 test_json_obj.test3 = [types.SimpleNamespace(**item) for item in test_json_data['test3']] print(test_json_obj.test3[0].test4)
额外建议
- 为避免KeyError,可使用
dict.get()方法设置默认值:test_json_data.get('test1', '默认内容') json.loads()未报错说明JSON格式完全合法,无需怀疑编码或解析问题- 静态JSON文件可直接打包到技能代码中(无需S3预签名URL),进一步简化逻辑,适合数据不频繁更新的场景
内容的提问来源于stack exchange,提问作者Mark Ryan
相关产品推荐
相关产品推荐

