When we try to publish the json to Azure Event hub, EventData converting the JSON string. Instead of JSON string I need the JSON only at the consumer end.
response = {"status":"Active", "code":400}
event_batch = await producer.create_batch()
event_batch.add(EventData(json.dumps(response)))
At the consumer end I am getting the event as { body: '{"status":"Active", "code":400}', 'sequence_numbe':1} like this. how can we get only Json at consumer end like this
{ body: {"status":"Active", "code":400}, 'sequence_numbe':1}
Can anyone help?
You could use body_as_json method to achieve your requirement.
Sample Implementation :
jsonbody = event.body_as_json(encoding='UTF-8')
This will directly return us the JSON Object
Alternate Approach :
Get it as string and then convert the same to json object.
jsonbody = json.loads(event.body_as_str(encoding='UTF-8')))
Related
I am trying to send JSON data from one parent lambda to multiple child lambdas. I am sending the data as JSON, it prints in the sending lambda with double quotes. However, the receiving lambda receives it only with single quotes:
event: [{'account': 'greg', 'caption': 'test test'}]
This is causing the error:
JSONDecodeError: Expecting property name enclosed in double quotes
I have tried using .encode() and base64.b64encode() but cannot get the correct format. What am I doing wrong? How do you send correctly formatted JSON between lambdas?
Sending Lambda:
response = client.invoke(
FunctionName = 'arn:aws:lambda:eu-west-1:xxxx:function:xxx',
InvocationType = 'RequestResponse',
Payload = json.dumps(sendData),
)
Receiving Lambda
def lambda_handler(event, context):
print("event: " + str(event))
handle_data(str(event))
return {
'statusCode': '200',
'body': 'Saved'
}
def handle_data(data):
data = json.loads(data)
print(data)
write_to_dynamo(data)
return print("Done")
The problem is how you are sending the data to your handle_data method. The event that you get in the lambda handler is already a list, you don't need to do a json.loads on it. What you are currently doing is converting the python list to a string and then trying to decode it as json (which won't work). Just send the data to your internal handler as is and don't try to do a json.loads on it (the aws api already does that conversion for you automatically)
Receiving Lambda
def lambda_handler(event, context):
handle_data(event)
return {
'statusCode': '200',
'body': 'Saved'
}
def handle_data(data):
print(data)
write_to_dynamo(data)
return print("Done")
Relevant snippet from the documentation:
When Lambda invokes your function handler, the Lambda runtime passes two arguments to the function handler:
The first argument is the event object. An event is a JSON-formatted document that contains data for a Lambda function to process. The Lambda runtime converts the event to an object and passes it to your function code. It is usually of the Python dict type. It can also be list, str, int, float, or the NoneType type.
The problem is that you aren't sending JSON. A JSON document is a string. Use json.dumps(e) and send the result, this will encode it as valid JSON rather than using python's built in output formatting.
My code looks like this:
payload = base64.b64decode(record['kinesis']['data'])
print("Decoded payload: " + payload)
In the log the result of the print line looks like this:
Decoded payload:
{
"timeStamp": 1509835693.7319956,
"thing": "testing/23"
}
Wouldn't I reference the timeStamp like this:
payload['timeStamp']
I am confused by what I have in this data structure. Can someone please explain to me what I have here and how I access the data inside the variable payload?
The decoded data is a string (as the error says), not a dictionary. You need to parse it before accessing its elements.
Considering your data is in JSON format, like the one you presented above:
import json
payload_str = base64.b64decode(record['kinesis']['data'])
payload = json.loads(payload_str) # parsing
print("Decoded payload: ", payload)
And now you have no problem accessing payload['timeStamp'], as far as the JSON does contain this field.
I have the following script:
import boto3
# Get the service resource
sqs = boto3.resource('sqs')
# Get the queue
queue = sqs.get_queue_by_name(QueueName='')
for message in queue.receive_messages():
print(message.body)
# Let the queue know that the message is processed
message.delete()
It returns the following as the message's body:
{"Records":[{"eventVersion":"2.0","eventSource":"aws:s3","awsRegion":"us-west-2","eventTime":"2017-03-03T11:06:25.329Z","eventName":"ObjectCreated:Copy","userIdentity":{"principalId":"AWS:<id>:<lambda_name>"},"requestParameters":{"sourceIPAddress":"54.186.104.49"},"responseElements":{"x-amz-request-id":"8577BEEB91F199BF","x-amz-id-2":"<>="},"s3":{"s3SchemaVersion":"1.0","configurationId":"PutFromSisterBucket","bucket":{"name":"<bucket_name>","ownerIdentity":{"principalId":"<>"},"arn":"arn:aws:s3:::<bucket_nmae>"},"object":{"key":"<object_key>","size":1990,"versionId":"anHi0ukirRiApp4jyoSTz2oVGOejR6tJ","sequencer":"0058B94E3141A83718"}}}]}
How do I get the value of the "key" inside the "object"?
Currently, the entire result is a string. Is there any way I can do without string indexing or regex match?
If the variable message is string you need to load it with json.loads, to parse to dict type in python, so you can use it like a json:
import json
for message in queue.receive_messages():
message_dict = json.loads(message)
record = message_dict["Records"][0]
content = record["s3"]["object"]["key"]
print(content)
I've got a really simple question, but I can't figure it out how to do it. The problem I have is that I want to send the following payload using Python and Requests:
{ 'on': true }
Doing it like this:
payload = { 'on':true }
r = requests.put("http://192.168.2.196/api/newdeveloper/lights/1/state", data = payload)
Doesn't work, because I get the following error:
NameError: name 'true' is not defined
Sending the true as 'true' is not accepted by my server, so that's not an option. Anyone a suggestion? Thanks!
You need to json encode it to get it to a string.
import json
payload = json.dumps({"on":True})
should be {'on': True}, capital T
Starting from requests 2.4.2, instead of passing in the payload with the data parameter, you can use the json parameter like this:
payload = {'on': True}
requests.put(url, json=payload)
And the request will be formatted correctly as a json payload (i.e. {'on': true}).
to make it be lower case like that (if that's what your endpoint requires) do in quotes {'on':'true'}
I am using boto library to read messages from SQS queue. My messages have text like this:
{ Command:XXXXXXXXXXX Key:XXXXXXX Input:XXXXXX} . Boto sends with base64 encoded and also reads it, so that if I read the message body then the text is there.
But how can I read the message like
Command = input['Command']
Key = input_message['Key'].split(',')
so that I can use those values for further processing...
I am quite new to Python also
Ok, you seem to have the input in some kind of a format - is it anything standardised? If not, you would need to parse the contents of your message and get the individual keys.
What I have been doing before in my projects was using JSON to facilitate data exchange between platforms.
If you do not have a luxury to edit your incoming data, you would need to do something like this (very naiive example):
input = "{ Command:XXXXXXXXXXX Key:XXXXXXX Input:XXXXXX }"
data = filter(lambda x: ":" in x, input.split())
message_dict = dict()
for item in data:
key, val = item.split(":")
message_dict[key] = val
Consider using good old fashioned JSON to easily send and receive dictionaries acrost the wire.
This test function verifies that the data format is very clear with JSON:
test_sqs.py
import json
import boto3
from moto import mock_sqs
#mock_sqs
def test_sqs():
sqs = boto3.resource('sqs', 'us-east-1')
queue = sqs.create_queue(QueueName='votes')
queue.send_message(MessageBody=json.dumps(
{'Command': 'drink', 'Key': 'beer', 'Input': 'tasty'}))
messages = queue.receive_messages()
assert len(messages) == 1
assert messages[0].body == (
'{"Input": "tasty", "Command": "drink", "Key": "beer"}')