I used to use the REST API, but since v2 I find myself using it more. Is there a proper way to return data "neatly" other than manipulating the database response before returning? I used to use the model feature with REST (v1). What's the recommended way to do the same here?
Here's an example of what I'm trying to do. I'm selecting specific columns, while avoiding the error:
An error occurred (ValidationException) when calling the UpdateItem operation: Invalid UpdateExpression: Attribute name is a reserved keyword "owner"
(got this for a column named "owner" and "name") and since integers/floats return as a "Decimal":
Object of type Decimal is not JSON serializable
I added the class to set them properly as integers/floats.
import json
import boto3
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)
def lambda_handler(event, context):
try:
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('SomeTable')
response_body = ''
status_code = 0
response = table.scan(
ProjectionExpression="#col1, #col2, #col3, #col4, #col5",
ExpressionAttributeNames={
"#col1": "col1",
"#col2": "col2",
"#col3": "col3",
"#col4": "col4",
"#col5": "col5"
}
)
items = response["Items"]
mapped_items = list(map(lambda item: {
'col1': item['col1'],
'col2': item['col2'],
'col3': item['col3'],
'col4': item['col4'],
'col5': item['col5'],
}, items))
response_body = json.dumps(mapped_items, cls=DecimalEncoder)
status_code = 200
except Exception as e:
response_body = json.dumps(
{'error': 'Unable to get metadata from SomeTable: ' + str(e)})
status_code = 403
json_response = {
"statusCode": status_code,
"headers": {
"Content-Type": "application/json"
},
"body": response_body
}
return json_response
This just looks too much for a simple "GET" request of some columns in a table
EDIT:
import json
import boto3
from boto3.dynamodb.conditions import Key
dynamodb = boto3.resource('dynamodb')
def lambda_handler(event, context):
try:
table = dynamodb.Table("mytable")
response = table.query(
ProjectionExpression='col1, col2, col3,col4, col5, col6'
)
response = json.loads(json.dumps(response, default=str))
return {
"statusCode": 200,
"body": response
}
except Exception as e:
print(f"Error: {e}")
return {
"statusCode": 500,
"body": "Error: Something went wrong!"
}
the above function returns the error:
Error: An error occurred (ValidationException) when calling the Query operation: Either the KeyConditions or KeyConditionExpression parameter must be specified in the request.
there is no condition for my case, i am requesting all rows.
I know I am not answering your question directly, but the point of having a lambda function in the API - Lambda - DynamoDB pattern is not to make lambda invisible (you can call DynamoDB directly, after all), but to abstract the database call in an efficient manner. For example, having the lambda aware of the structure of the database would save you from making expensive scan
s and do a more lightweight query
instead.