1 Answer
- Newest
- Most votes
- Most comments
2
Your question and objective have multiple pieces:
- Q: How to handle encoding decimal values to JSON.
- A: Use a custom encoder like how you are doing
- Documentation: https://stackoverflow.com/questions/1960516/python-json-serialize-a-decimal-object
- Q: Avoiding reserved words
- A: Use ProjectionExpression with ExpressionAttributeNames like how you are doing
- Documentation: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html
- Q: Simplest way to return a get response from DynamoDB using python
- A:
import json
import uuid
import os
import boto3
from datetime import datetime
from decimal import Decimal
class DecimalEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Decimal):
return str(obj)
return json.JSONEncoder.default(self, obj)
# Prepare DynamoDB client
USERS_TABLE = os.getenv('USERS_TABLE', None)
dynamodb = boto3.resource('dynamodb')
ddbTable = dynamodb.Table(USERS_TABLE)
def lambda_handler(event, context):
route_key = f"{event['httpMethod']} {event['resource']}"
# Set default response, override with data from DynamoDB if any
response_body = {'Message': 'Unsupported route'}
status_code = 400
headers = {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
try:
# Get a list of all Users
if route_key == 'GET /users':
ddb_response = ddbTable.scan(Select='ALL_ATTRIBUTES')
# return list of items instead of full DynamoDB response
response_body = ddb_response['Items']
status_code = 200
# CRUD operations for a single User
# Read a user by ID
if route_key == 'GET /users/{userid}':
# get data from the database
ddb_response = ddbTable.get_item(
Key={'userid': event['pathParameters']['userid']}
)
# return single item instead of full DynamoDB response
if 'Item' in ddb_response:
response_body = ddb_response['Item']
else:
response_body = {}
status_code = 200
except Exception as err:
status_code = 400
response_body = {'Error:': str(err)}
print(str(err))
return {
'statusCode': status_code,
'body': json.dumps(response_body, cls=DecimalEncoder),
'headers': headers
}
Your mapped_items
object is just remapping the same values as exist in the items response, so if you don't need to rename those values in the json, you don't need that step. For example, this is the body of your response with and without the mapped_items:
With mapped_items
[{\"col1\": \"1\", \"col2\": \"2\", \"col3\": \"3\", \"col4\": \"4\", \"col5\": \"5\", \"owner\": \"ddd\"}]
Without mapped_items (just returning response["Items"])
[{\"col3\": \"3\", \"col4\": \"4\", \"col5\": \"5\", \"owner\": \"ddd\", \"col1\": \"1\", \"col2\": \"2\"}]
Also, it is better practice to establish the dynamoDB connection outside of the request handler (this is demonstrated in the above code). That way, if a warm invocation occurs, that invocation will use the existing dynamodDB connection and complete quicker
References: https://catalog.workshops.aws/serverless-patterns/en-US
answered a year ago
Relevant content
- Accepted Answerasked 2 years ago
- Accepted Answerasked a year ago
- AWS OFFICIALUpdated 14 days ago
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated 5 months ago
- AWS OFFICIALUpdated 10 days ago