Python - AWS Lambda从JSON输入中提取密钥

时间:2018-01-13 20:49:34

标签: python json amazon-web-services lambda

我正在尝试实现一个从cloudwatch获取事件并打印结果的函数。我能够获得该事件,但我想从该JSON中提取一个特定的密钥。

这是我的功能:

import json
    def lambda_handler(event, context):
        print("Received event: " + json.dumps(event, indent=2)) 
        message = event['Records'][0]['Sns']['Message']
        print(message)

该事件来自Cloudwatch:

"Records": [
{
"EventVersion": "1.0", 
"EventSubscriptionArn": "arn:aws:sns:us-east-1:xxxxxxxxxxxxx:bhuvi:XXXXXXXXXXXXXXXXXXXXXXXXXX", 
"EventSource": "aws:sns", 
"Sns": {
"SignatureVersion": "1", 
"Timestamp": "2018-01-13T19:18:44.369Z", 
"Signature": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
"SigningCertUrl": "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.pem", 
"MessageId": "4b76b0ea-5e0f-502f-81ec-e23e03dbaf01", 
"Message": "{\"AlarmName\":\"test\",\"AlarmDescription\":\"test\",\"AWSAccountId\":\"xxxxxxxxxxxxx\",\"NewStateValue\":\"ALARM\",\"NewStateReason\":\"Threshold Crossed: 1 out of the last 1 datapoints [2.6260535333900545 (13/01/18 19:13:00)] was greater than or equal to the threshold (1.0) (minimum 1 datapoint for OK -> ALARM transition).\",\"StateChangeTime\":\"2018-01-13T19:18:44.312+0000\",\"Region\":\"US East (N. Virginia)\",\"OldStateValue\":\"OK\",\"Trigger\":{\"MetricName\":\"CPUUtilization\",\"Namespace\":\"AWS/RDS\",\"StatisticType\":\"Statistic\",\"Statistic\":\"AVERAGE\",\"Unit\":null,\"Dimensions\":[{\"name\":\"DBInstanceIdentifier\",\"value\":\"myrds\"}],\"Period\":300,\"EvaluationPeriods\":1,\"ComparisonOperator\":\"GreaterThanOrEqualToThreshold\",\"Threshold\":1.0,\"TreatMissingData\":\"\",\"EvaluateLowSampleCountPercentile\":\"\"}}", 
"MessageAttributes":
{}
, 
"Type": "Notification", 
"UnsubscribeUrl": "https://sns.us-east-1.amazonaws.com/?xcsgagrgrwgwrg", 
"TopicArn": "arn:aws:sns:us-east-1:xxxxxxxxxxxxx:bhuvi", 
"Subject": "ALARM: \"test\" in US East (N. Virginia)"
}
}
]
}

我的提取命令(Upto消息)及其结果:

message = event['Records'][0]['Sns']['Message']
        print(message)

结果

{
    "AlarmName": "test",
    "AlarmDescription": "test",
    "AWSAccountId": "xxxxxxxxxxxxx",
    "NewStateValue": "ALARM",
    "NewStateReason": "Threshold Crossed: 1 out of the last 1 datapoints [2.6260535333900545 (13/01/18 19:13:00)] was greater than or equal to the threshold (1.0) (minimum 1 datapoint for OK -> ALARM transition).",
    "StateChangeTime": "2018-01-13T19:18:44.312+0000",
    "Region": "US East (N. Virginia)",
    "OldStateValue": "OK",
    "Trigger": {
        "MetricName": "CPUUtilization",
        "Namespace": "AWS/RDS",
        "StatisticType": "Statistic",
        "Statistic": "AVERAGE",
        "Unit": null,
        "Dimensions": [
            {
                "name": "DBInstanceIdentifier",
                "value": "myrds"
            }
        ],
        "Period": 300,
        "EvaluationPeriods": 1,
        "ComparisonOperator": "GreaterThanOrEqualToThreshold",
        "Threshold": 1,
        "TreatMissingData": "",
        "EvaluateLowSampleCountPercentile": ""
    }

我想从此消息窗格中提取一些值。

例如:我想提取姓名。所以我尝试了下面的命令,但不幸的是它不起作用。谁可以帮我这个事? enter image description here

我的代码:

message = event['Records'][0]['Sns']['Message']['Trigger']['Dimensions']['name']
    print(message)

ERROR:

{
  "stackTrace": [
    [
      "/var/task/lambda_function.py",
      14,
      "lambda_handler",
      "message = event['Records'][0]['Sns']['Message']['Trigger']['Dimensions']['name']"
    ]
  ],
  "errorType": "TypeError",
  "errorMessage": "string indices must be integers"
}

2 个答案:

答案 0 :(得分:3)

所以有3个问题:

问题1:在您的示例事件中,['Records'][0]['Sns']['Message']是JSON格式的str。这意味着您需要解析这样的字典:

 message = event['Records'][0]['Sns']['Message']
 message = json.loads(message)

问题2: message['Trigger']['Dimensions']list,但您尝试访问它,就好像它是dict一样。因此,您只需将代码更改为:

message = message['Trigger']['Dimensions'][0]['name']

问题3: Messagestr,这意味着你需要验证它是普通的str还是json str(否则你将会有多种结构和类型的问题)。为此,您的代码可能如下所示:

 message = event['Records'][0]['Sns']['Message']
    if isinstance(message, str):
        try:
            message = json.loads(message)
        except Exception as e:
            print(e) # Or do nothing, this is just to log the error
    elif isinstance(message, list):
        message = message[0]
    # Maybe evaluate bool, tuple, etc other types

    print('RESPONSE', message['Trigger']['Dimensions'][0]['name'] if isinstance(message, dict) else message)

但是我还建议让它更加可扩展,迭代你知道的list元素。出于安全原因(尝试避免空指针异常),请使用带有默认值的get()函数。 http://www.tutorialspoint.com/python/dictionary_get.htm。尝试创建一个函数来解析结构并使其可重用。

祝你好运!

答案 1 :(得分:1)

正如Records是一个列表一样,所以你使用['Records'][0]['Sns']...Dimensions也是如此,所以你需要再次访问第一个元素。