I'm trying to set-up an AWS-lambda using aws-sdk-go that is triggered whenever a new user
is added to a certain dynamodb table.
Everything is working just fine but I can't find a way to unmarshal a map map[string]DynamoDBAttributeValue
like:
{ "name": { "S" : "John" }, "residence_address": { "M": { "address": { "S": "some place" } } } }
To a given struct, for instance, a User
struct. Here is shown an example of unsmarhaling a map[string]*dynamodb.AttributeValue
into a given interface, but I can't find a way to do the same thing with map[string]DynamoDBAttributeValue
even though these types seem to fit the same purposes.
map[string]DynamoDBAttributeValue
is returned by a events.DynamoDBEvents
from package github.com/aws/aws-lambda-go/events
. This is my code:
package handler import ( "context" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" "github.com/aws/aws-sdk-go/service/dynamodb" ) func HandleDynamoDBRequest(ctx context.Context, e events.DynamoDBEvent) { for _, record := range e.Records { if record.EventName == "INSERT" { // User Struct var dynamoUser model.DynamoDBUser // Of course this can't be done for incompatible types _ := dynamodbattribute.UnmarshalMap(record.Change.NewImage, &dynamoUser) } } }
Of course, I can marshal record.Change.NewImage
to JSON and unmarshal it back to a given struct, but then, I would have to manually initialize dynamoUser
attributes starting from the latter ones.
Or I could even write a function that parses map[string]DynamoDBAttributeValue
to map[string]*dynamodb.AttributeValue
like:
func getAttributeValueMapFromDynamoDBStreamRecord(e events.DynamoDBStreamRecord) map[string]*dynamodb.AttributeValue { image := e.NewImage m := make(map[string]*dynamodb.AttributeValue) for k, v := range image { if v.DataType() == events.DataTypeString { s := v.String() m[k] = &dynamodb.AttributeValue{ S : &s, } } if v.DataType() == events.DataTypeBoolean { b := v.Boolean() m[k] = &dynamodb.AttributeValue{ BOOL : &b, } } // . . . if v.DataType() == events.DataTypeMap { // ? } } return m }
And then simply use dynamodbattribute.UnmarshalMap
, but on events.DataTypeMap
it would be quite a tricky process.
Is there a way through which I can unmarshal a DynamoDB record coming from a events.DynamoDBEvent
into a struct with a similar method shown for map[string]*dynamodb.AttributeValue
?
I tried the function you provided, and I met some problems with events.DataTypeList
, so I managed to write the following function that does the trick:
// UnmarshalStreamImage converts events.DynamoDBAttributeValue to struct func UnmarshalStreamImage(attribute map[string]events.DynamoDBAttributeValue, out interface{}) error { dbAttrMap := make(map[string]*dynamodb.AttributeValue) for k, v := range attribute { var dbAttr dynamodb.AttributeValue bytes, marshalErr := v.MarshalJSON(); if marshalErr != nil { return marshalErr } json.Unmarshal(bytes, &dbAttr) dbAttrMap[k] = &dbAttr } return dynamodbattribute.UnmarshalMap(dbAttrMap, out) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With