What you are printing is a python dict, it looks sort of like JSON but is not JSON, it is the representation of a python dict. That means it will have True / False instead of true / false, it will have ' instead of ", etc.
You could do print(json.dumps(event)) instead.
Anyway, the actual problem is that invokingEvent is yet another JSON, but in its string form, you need to to json.loads that nested JSON string. You can see that because the value after invokingEvent is inside another set of '...', therefore it is a string, not a parsed dict already.
invoking_event = json.loads(event['invokingEvent'])
change_type = invoking_event["configurationItemDiff"]["changeType"]
ruleParameters would be another nested JSON which needs parsing first if you wanted to use it.
Malformed JSON in AWS Lambda using Python.
Access json request from python in python AWS lambda function - Stack Overflow
How to retrieve well formatted JSON from AWS Lambda using Python - Stack Overflow
Python AWS Lambda Event JSON - Stack Overflow
Hello LeanPython Sub-reddit!
I come to you because I have a problem formatting JSON in AWS Lambda.
I would like to tell you a little more, what happens is that I am developing an API in AWS Lambda, I created the database in PostgreSQL, and I am using Python to perform the queries, what happens is that I had a datatimes management error, because these values could not be formatted in a JSON, so I decided to make an encoder in a class which is responsible for carrying out this process of formatting it to JSON, but what happens is that it generates a JSON which is very poorly readable, in addition to being a headache when trying to manipulate it in the Frontend, below I will show you what I did and I would like to consult with you about a possible solution to this problem, please.
Below you will find the encoder class I was talking about:
class DateTimeEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, datetime):
return o.isoformat()
return json.JSONEncoder.default(self, o)
In the following function I am using json.dumps to format the output of the database query into JSON, in conjunction with the encoder:
def lambda_handler(event, context):
cur = conn.cursor(cursor_factory=RealDictCursor)
cur.execute("SELECT * FROM users")
results = cur.fetchall()
return json.dumps(results, cls=DateTimeEncoder)When deploying this in AWS in a Lambda, and when making the HTTP request through Postman, it generates the following poorly formatted output:
"[{\"id_usuario\": 2, \"cc\": \"123456789\", \"telefono\": \"987654321\", \"nombre\": \"John\", \"apellido\": \"Doe\", \"fecha_registro\": \"2023-07-03T02:34:38.452359\"}, {\"id_usuario\": 3, \"cc\": \"1013655876\", \"telefono\": \"2085686\", \"nombre\": \"Jane\", \"apellido\": \"Doe\", \"fecha_registro\": \"2023-07-03T20:08:42.603593\"}]"What I want is for the above JSON to look like this:
[
{
"id_usuario": 2,
"cc": "123456789",
"telefono": "987654321",
"nombre": "John",
"apellido": "Doe",
"fecha_registro": "2023-07-03T02:34:38.452359"
},
{
"id_usuario": 3,
"cc": "1013655876",
"telefono": "2085686",
"nombre": "Jane",
"apellido": "Doe",
"fecha_registro": "2023-07-03T20:08:42.603593"
}
]
If you ask me, I have made other queries that have not had to use the json.dumps and it has generated the JSON with the correct format, however, when I implement the json.dumps in conjunction with the encoder, it generates that output which is difficult to read, I sincerely hope you can help me because I don't know what else to do.
In your lambda function you should return a response object with a JSON object in the response body.
# Lambda Function
def get_json(event, context):
"""Retrieve JSON from server."""
# Business Logic Goes Here.
response = {
"statusCode": 200,
"headers": {},
"body": json.dumps({
"message": "This is the message in a JSON object."
})
}
return response
Don't use json.dumps()
I had a similar issue, and when I just returned "body": content instead of "body": json.dumps(content) I could easily access and manipulate my data. Before that, I got that weird form that looks like JSON, but it's not.
You have to use json.loads not json.dumps.
Try this:
import json
event = {
"Records":[
{
"messageId":"916f5e95-b2f6-4148-9c62-2ac8e764f06c",
"receiptHandle":"AQEBmLuoGWtLtFFgvyCFdSPMJh2HKgHOIPWNUq22EOwCzGT8iILZm97CE6j4J6oR71ZpDr3sgxQcJyVZ+dmmvGl+fFftT9GCJqZYrjMGsR2Q6WsMd8ciI8bTtDXyvsk8ektd7UGfh4gxIZoFp7WUKVRcMEeBkubKd8T4/Io81D0l/AK7MxcEfCj40vWEsex1kkGmMRlBtdSeGyy7fJgUq5CFAYWciiWtbSit8S0Y38xZPmsIFhoxP0egQRoJcW4aUgMi469Gj5+khizetybtgC8vux5NCg/IejxcCueXkQ7LKVF8kfRdqRSUYB6DsOrGgfmZpK4wpXIarByNz0R2p7J88meYpj2IVULv/emXsSYaKG4rXnpbH4J9ijbLWckYLAd7wPDzCYri1ZSTgAz0kchsEw==",
"body":"{\n\"name\": \"aniket\",\n\"tag\": \"hello\"\n}",
"attributes":{
"ApproximateReceiveCount":"1",
"SentTimestamp":"1602046897707",
"SenderId":"AIDAR3BXDV4FCWXL56NUU",
"ApproximateFirstReceiveTimestamp":"1602046897712"
},
"messageAttributes":{
},
"md5OfBody":"98da683a47692b39c1d43bd4fa21ed89",
"eventSource":"aws:sqs",
"eventSourceARN":"arn:aws:sqs:ap-south-1:126817120010:documentation",
"awsRegion":"ap-south-1"
}
]
}
parsed = json.loads(event['Records'][0]['body'])
print(json.dumps(parsed, indent=4, sort_keys=True))
Output:
{
"name": "aniket",
"tag": "hello"
}
Try using json.loads(string) to deserialize the json.
Also, I don't believe you need to specify the index [0] since 'body' is an object and not an array.
I'm not sure if this is what you want, but you can just do 'body': json_data. I tested this now in my λ function:
Lambda function
import json
def lambda_handler(event, context):
json_data = [{"Dp_Record_Id": 2,
"DP_TYPE": "NSDL",
"DP_ID": "40877589",
"CLIENT_ID": "1232",
"Default_flag": "Y"}]
return {'statusCode': 200,
'headers': {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": 'GET, POST, PUT, DELETE, OPTIONS'
},
'body': json_data
}
Result
Response:
{
"statusCode": 200,
"headers": {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS"
},
"body": [
{
"Dp_Record_Id": 2,
"DP_TYPE": "NSDL",
"DP_ID": "40877589",
"CLIENT_ID": "1232",
"Default_flag": "Y"
}
]
}
I ran into the same issue while I was creating an API by doing things from my memory. Posting this answer for my future self and others.
The issue was that whatever I return in the lambda is getting passed as response to the API. Instead only the data inside body should be passed as response.
This was happening because when I created the resource I forgot to check the checkbox to Use Lambda Proxy Integration. Here is what you have to do:
- Delete your existing method and create a new one. This time make sure you check Use Lambda Proxy Integration.

- Create a deployment to your stage. Until this is done, the change will not reflect. This is where I got stuck and spend most of my time.
Convert into dict and then try
import json
import boto3
s3 = boto3.client('s3')
def lambda_handler(event, context):
s3_clientobj = s3.get_object(Bucket='avcdf-bulk-dev', Key='RIXML/josnfile.json')
s3_clientdata = s3_clientobj['Body'].read().decode('utf-8')
#print(s3_clientdata)
clientdata_dict = json.loads(s3_clientdata)
print(clientdata_dict)
print(clientdata_dict['Research']['@researchID'])
You can access the above mentioned properties like below,
s3_clientobj = s3.get_object(Bucket='avcdf-bulk-dev', Key='RIXML/josnfile.json')
s3_clientdata = json.loads(s3_clientobj['Body'].read().decode('utf-8'))
print("%s, %s, %s" % (s3_clientdata['Research']['@researchID'], s3_clientdata['Research']['Product']['@productID'], s3_clientdata['Research']['Product']['Content']['Resource']['@resourceID']))
So there are 3 problems:
Problem 1: In your example event, ['Records'][0]['Sns']['Message'] is a str in JSON format. That means that you need to parse to a dict like this:
message = event['Records'][0]['Sns']['Message']
message = json.loads(message)
Problem 2: message['Trigger']['Dimensions'] is a list but you are trying to access it like if it were a dict. So you only need to change your code to:
message = message['Trigger']['Dimensions'][0]['name']
Problem 3: Message is a str that means that you need to verify that is a plain str or json str (otherwise you are going to have problems with multiple structures and types). For that your code could look like:
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)
However I would also recommend to make it more extensible iterating the elements that you know are list. And for safety reasons (trying to avoid null pointer exceptions), use the get() function with a default value. http://www.tutorialspoint.com/python/dictionary_get.htm . Try maybe to create a function to parse structures and make it reusable.
Good luck!
Just as Records is a list, so you use ['Records'][0]['Sns']..., so is Dimensions, so again you need to access the first element.