将AWS Lambda事件JSON转换为Python字典时遭遇JSONDecodeError错误的技术求助
解决AWS Lambda中SNS事件JSON的JSONDecodeError问题
错误原因分析
你的代码里出现JSONDecodeError,核心问题出在手动构造的测试字符串st里的转义处理错误。具体来说:
- 在
Message字段的内容中,你用了\\'来转义单引号,但Python的三重引号字符串会把\\解析成单个\,导致最终传递给json.loads的字符串里出现\'——而JSON规范里并不支持单引号的转义,这直接触发了解析错误。 - 另外要注意:SNS事件的
Message字段本身就是一个嵌套的JSON字符串,所以即使外层JSON解析成功,你还需要再解析一次这个字段才能拿到Redshift的事件详情。
解决方案
1. 修正测试代码的字符串转义
如果你要手动构造测试字符串,给三重引号字符串加上r前缀(原始字符串),这样所有转义字符会被原样保留,让json.loads能正确解析:
import json # 加上r前缀使用原始字符串 st = r""" { "Records":[ { "EventSource":"aws:sns", "EventVersion":"1.0", "EventSubscriptionArn":"arn:aws:sns:us-east-2:427128480143:terraform-redshift-sns-topic:cbdfec04-7502-4509-9954-435e2ddc5e3c", "Sns":{ "Type":"Notification", "MessageId":"fecb7b39-a861-5450-9179-23d0ce68f268", "TopicArn":"arn:aws:sns:us-east-2:427128480243:terraform-redshift-sns-topic", "Subject":"AmazonRedshiftINFO - Cluster Created", "Message":"{\"Event Source\":\"cluster\",\"Resource\":\"qa-redshift-cluster\",\"Event Time\":\"2021-04-08 20:12:57.466\",\"Identifier Link\":\"https://console.aws.amazon.com/redshift/home?region=us-east-2#cluster-details:cluster=qa-redshift-cluster \",\"Severity\":\"INFO\",\"Category\":[\"Management\"],\"About this Event\":\"http://docs.aws.amazon.com/redshift/latest/mgmt/working-with-event-notifications.html#REDSHIFT-EVENT-2000 \",\"Event Message\":\"Amazon Redshift cluster \\'qa-redshift-cluster\\' has been created at 2021-04-08 20:12 UTC and is ready for use.\"}", "Timestamp":"2021-04-08T20:12:57.905Z", "SignatureVersion":"1", "Signature":"jS2AK8hf/rebeXMsfFw0DJx+788w+RiDTXyAbLNZzYdE5Mlhi6GRRIns8VaAJZc5otXkkhGshvgvuE0JsUiOhXBccGEJY6Z+lhx6cLSQoEdQB0DRfwltWKOfpQ88LZXJuKCxYcsPL3y5veBdjJqwjdBZtcVYV9BYRhQvT6q/0MpDcJeOYzMkdpR2ULX5B7GasZ3AV0WbKxIjjzFSd3GNud2m85obRrB//NHQwqN6ydvg7PaN/sXuyJjmguRok27O6YNkIqzKjC4JxDbTl4BwyIbck59edbHC5kxmfpoc/RqjF/kUGaqnf0HYOUuMfDT85+9wYVz8vFFER1v3NnKRLA==", "SigningCertUrl":"https://sns.us-east-2.amazonaws.com/SimpleNotificationService-010a507c1833636cd94bdd98bd93083a.pem", "UnsubscribeUrl":"https://sns.us-east-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-2:427128480243:terraform-redshift-sns-topic:cbdfec04-7502-4509-9954-435e7ddc5e3c", "MessageAttributes":{ } } } ] } """ data1 = json.loads(st) # 解析嵌套的Message内容 redshift_event = json.loads(data1['Records'][0]['Sns']['Message']) print("事件类型:", redshift_event['Event Message']) print("Redshift集群标识符:", redshift_event['Resource'])
2. 实际Lambda函数中的正确写法
在真实的Lambda环境中,AWS会自动把传入的SNS事件解析为Python字典,你不需要手动调用json.loads处理外层事件,只需要解析嵌套的Message字段即可:
import json def lambda_handler(event, context): # 直接从已解析的event字典中获取SNS消息 sns_message = event['Records'][0]['Sns']['Message'] # 解析嵌套的Redshift事件JSON redshift_event = json.loads(sns_message) # 提取你需要的字段 event_type = redshift_event['Event Message'] cluster_identifier = redshift_event['Resource'] print(f"获取到Redshift事件: {event_type}") print(f"集群标识符: {cluster_identifier}") return { 'statusCode': 200, 'body': json.dumps({ 'cluster_identifier': cluster_identifier, 'event_type': event_type }) }
总结
- 测试时构造JSON字符串,记得用原始字符串(
r"""...""")避免转义被Python提前解析 - 实际Lambda运行时,外层事件已经是解析好的字典,只需处理嵌套的
Message字段即可
内容的提问来源于stack exchange,提问作者Deepak_Spark_Beginner
相关产品推荐
相关产品推荐

