I have a lambda function that is triggered from a DynamoDB stream event. The object it accepts is a DynamoDBEvent
from the Amazon.Lambda.DynamoDBEvents
Nuget package.
public async Task FunctionHandler(DynamoDBEvent event, ILambdaContext context)
{
foreach (var record in event.Records)
{
var newImage = event.Dynamodb.NewImage; // Or "OldImage" property
var myObject = new MyObject();
myObject.ItemId = newImage["ItemId"].N;
myObject.IdList = newImage["IdList"].NS;
myObject.CustomerName = newImage["CustomerName"].S;
}
}
Is it possible to easily convert this event to my own class, like the one below, eg:
public class MyObject
{
public int ItemId { get; set; }
public List<int> IdList { get; set; }
public string CustomerName { get; set; }
}
Without having to create my own mapper that manipulates the DynamoDBEvent object for each individual property of every type?
The AttributeValue
class contains lots of different properties, one for each type the DynamoDb supports and my object may become complex with nested properties in the future.
The Document model from the DynamodDB library seems to be able to do it already...
NewImage
and OldImage
is of type Dictionary<string, AttributeValue>
.
The Amazon.Lambda.DynamoDBEvents
Nuget package that contains the definitions for DynamoDBEvent
already has a dependency on the package AWSSDK.DynamoDBv2
which already contains the code for the .NET DynamoDB Document Model to convert from a Dictionary<string, AttributeValue>
to another object.
We can write a helper method that utilises FromAttributeMap
and FromDocument
to convert it:
using Amazon;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.DynamoDBv2.Model;
public class DynamoDbStreamToObject
{
private static readonly AmazonDynamoDBConfig ClientConfig = new AmazonDynamoDBConfig { RegionEndpoint = RegionEndpoint.EUWest1 };
private static readonly DynamoDBContext DynamoDbContext = new DynamoDbContext(newAmazonDynamoDBClient(ClientConfig));
public static T Convert<T>(Dictionary<string, AttributeValue> dynamoDbImage)
{
var dynamoDocument = Document.FromAttributeMap(dynamoDbImage);
return DynamoDbContext.FromDocument<T>(dynamoDocument);
}
}
First it converts Dictionary<string, AttributeValue>
to an Amazon DynamoDB Document
and from that to your object.
Your function handler can now be simplified by using this helper method to the following:
public async Task FunctionHandler(DynamoDBEvent event, ILambdaContext context)
{
foreach (var record in input.Records)
{
var newImage = event.Dynamodb.NewImage; // Or "OldImage" property
var myObject = DynamoDbStreamToObject.Convert<MyObject>(newImage);
}
}
Unfortunately this requires a kind've redundant DynamoDBContext (Redundant because it's not connecting to DynamoDB itself), but it seems to work.