I use AWS Lambda with DynamoDB using golang.
My DynamoDB table use lowercase attribute names such as id
or name
.
In Go, if I want to be able to marshal a struct correctly, I have to name fields starting with a capital letter.
type Item struct {
ID string
Name string
}
To put an item into my DynamoDB table, I have to marshal it into a map[string]*dynamodb.AttributeValue
, using dynamodbattribute.MarshalMap
function.
item := Item{
ID: "xxxx",
Name: "yyyy"
}
av, _ := dynamodbattribute.MarshalMap(item)
Of course, this will create a map
using names written as ID
and Name
, which are incompatible with id
and name
from the dynamodb table.
Reading the documentation, I found that you can use a custom encoder, and enable json tags.
type Item struct {
ID string `json="id"`
Name string `json="name"`
}
func setOpts(encoder *dynamodbattribute.Encoder) {
// Not sure which one I sould set
// So I set them both :)
encoder.SupportJSONTags = true
encoder.MarshalOptions.SupportJSONTags = true
}
func main() {
encoder := dynamodbattribute.NewEncoder(setOpts)
encoder.Encode(...)
}
But here the encoder.Encode()
method is only used to create a dynamodb.AttributeValue
, and not a map[string]*dynamodb.AttributeValue
.
Is there a way to use a custom encoder with MarshalMap
? Or am I using it in a wrong way?
EDIT:
Okay so as Zak pointed out, there is a dynamodbav
tag that can be used.
I also found out that I was using json
tags in a wrong way. I should use the syntax json:"id"
instead of json="id"
.
Indeed, DynamoDB SDK uses the json tag if available, and this one can be overrided by the dynamodbav
.
So all I had to do was to make my structure looks like this and it worked
type Item struct {
ID string `json:"id"`
Name string `json:"name"`
}
Dynamo's built in marshalling, from MarshalMap(...)
can support struct tags, similar to json.
You can add them to the type that you are marshalling, like so:
type Item struct {
ID string `dynamodbav:"id"`
Name string `dynamodbav:"name"`
}