I've been using Protobuf for object definitions to be used when communicating with DynamoDB. Until now, such objects would look like this:
type Record struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,2,opt,name=id,json=id,proto3" dynamodbav:"id,omitempty" json:"id,omitempty"`
Name string `protobuf:"bytes,3,opt,name=name,json=name,proto3" dynamodbav:"name,omitempty" json:"name,omitempty"`
OrgId string `protobuf:"bytes,4,opt,name=org_id,json=orgId,proto3" dynamodbav:"org_id,omitempty" json:"org_id,omitempty"`
AccountId string `protobuf:"bytes,7,opt,name=account_id,json=accountId,proto3" dynamodbav:"account_id,omitempty" json:"account_id,omitempty"`
Address string `protobuf:"bytes,9,opt,name=address,proto3" dynamodbav:"address,omitempty" json:"address,omitempty"`
BillingTitle string `protobuf:"bytes,10,opt,name=billing_title,json=billingTitle,proto3" dynamodbav:"billing_title,omitempty" json:"billing_title,omitempty"`
Language string `protobuf:"bytes,11,opt,name=language,proto3" dynamodbav:"language,omitempty" json:"language,omitempty"`
Personal string `protobuf:"bytes,12,opt,name=personal,proto3" dynamodbav:"personal,omitempty" json:"personal,omitempty"`
Phonenumber string `protobuf:"bytes,13,opt,name=phonenumber,proto3" dynamodbav:"phonenumber,omitempty" json:"phonenumber,omitempty"`
Postalcode string `protobuf:"bytes,14,opt,name=postalcode,proto3" dynamodbav:"postalcode,omitempty" json:"postalcode,omitempty"`
ProjectId string `protobuf:"bytes,15,opt,name=project_id,json=projectId,proto3" dynamodbav:"project_id,omitempty" json:"project_id,omitempty"`
Remarks string `protobuf:"bytes,16,opt,name=remarks,proto3" dynamodbav:"remarks,omitempty" json:"remarks,omitempty"`
}
The table I'm adding these objects to has a global secondary index with project_id as the sort-key but this field isn't always populated. So, when I went to do a PutObject operation on the table, like this:
record := Record {
Id: "A000",
Name: "Some Record",
OrgId: "O000"
}
attrs, err := dynamodbattribute.MarshalMap(&record)
if err != nil {
panic(err)
}
if _, err := conn.PutItem(&dynamodb.PutItemInput{
TableName: aws.String(tableName),
Item: attrs
}); err != nil {
panic(err)
}
this code wouldn't panic and I'd see the value in DynamoDB. However, after removing the omitempty clause from all the dynamodbav tags, I notice that this now fails with the following error:
ValidationException: Invalid attribute value type
status code: 400, request id: 6a626232-fcd4-4999-afe4-3df5769ce1b2
After some further investigation, I see that the object is serialized as:
map[account_id:{
NULL: true
} address:{
NULL: true,
} billing_title:{
NULL: true
} id:{
S: "A000"
} name:{
S: "Some Record"
} language:{
NULL: true
} org_id:{
S: "O000"
} personal:{
NULL: true
} phonenumber:{
NULL: true
} postalcode:{
NULL: true
} project_id:{
NULL: true
} remarks:{
NULL: true
}
when omitempty is not included but serializes to:
map[id:{
S: "A000"
} name:{
S: "Some Record"
} org_id:{
S: "O000"
}
when omitempty is included.
I'd like to get the former with default values rather than NULL: true but I don't see any serialization options for this. Is there a way to do this without implementing the DynamoDB marshaler interface?