Search code examples
pythonamazon-web-servicesaws-lambdaaws-api-gateway

Extract content from lambda event


I have a lambda with API gateway. So far I have tested it via "Test" tab in aws console and using below json file

{
  "datasource": "XXX",
  "action": "update",
  "code": "test",
  "time": "2023-03-20T11:39:50.0038136+00:00",
  "data": {
    "invoice": {
      "invoiceId": "xxxx58d752f6f7f5d",
      "type": "fixed",
      "value": 5000
    }
  }
}

In my lambda

def lambda_handler(event, context):
    s1 = json.dumps(event)
    inv_event = json.loads(s1)
    # Im reading values like below
    invoiceId = inv_event['data']['invoice']['invoiceId']

This is working fine as expected. But now I am trying to hit this via api gateway and post the same json via postman and this started failing with error "[ERROR] TypeError: string indices must be integers". I have done a print of incoming event when call via postman and its like below

{'resource': '/hello', 'path': '/hello', 'httpMethod': 'POST', 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate, br', 'CloudFront-Forwarded-Proto': 'https', 'CloudFront-Is-Desktop-Viewer': 'true', 'CloudFront-Is-Mobile-Viewer': 'false', 'requestContext': {'resourceId': '3mm431', 'resourcePath': '/hello', 'httpMethod': 'POST', 'extendedRequestId': 'DoIXeECnIAMF8eg=', 'requestTime': '19/Apr/2023:13:34:01 +0000', 'path': '/Prod/hello', 'accountId': '597878062269', 'protocol': 'HTTP/1.1', 'stage': 'Prod', 'domainPrefix': 'xxxx', 'requestTimeEpoch': 1681911241190, 'requestId': 'ba1ee0c7-8b57-42bc-9335-d5548b1a084a', 'identity': {'cognitoIdentityPoolId': None, 'accountId': None, 'cognitoIdentityId': None, 'caller': None, 'sourceIp': '86.139.218.222', 'principalOrgId': None, 'accessKey': None, 'cognitoAuthenticationType': None, 'cognitoAuthenticationProvider': None, 'userArn': None, 'userAgent': 'PostmanRuntime/7.32.2', 'user': None}, 'domainName': 'xxxx.execute-api.xxxx.amazonaws.com', 'apiId': 'xxxx'}, 'body': '{\r\n      \"datasource\": \"XXX\",\r\n      \"action\": \"update\",\r\n      \"code\": \"test\",\r\n      \"time\": \"2023-03-20T11:39:50.0038136+00:00\",\r\n      \"data\": {\r\n        \"invoice\": {\r\n          \"invoiceId\": \"xxxx58d752f6f7f5d\",\r\n          \"type\": \"fixed\",\r\n          \"value\": 5000\r\n        }\r\n      }\r\n    }', 'isBase64Encoded': False}

Is there a way for me to extract the posted json and load it as json.loads?


Solution

  • You're just converting the entire event from a dict to a JSON string, and back to a dict with these two lines, they aren't actually accomplishing anything:

        s1 = json.dumps(event)
        inv_event = json.loads(s1)
    

    The body attribute of the event is a string representation of the request payload that was sent to API Gateway. You need to tell Python that that specific string is JSON, and needs to be parsed into a dict.

    inv_event = json.loads(event['body'])
    invoiceId = inv_event['data']['invoice']['invoiceId']