Estoy usando una función AWS Lambda escrita en Go with Dynamo Stream, pero no veo ninguna manera de poder organizar el antiguo & nueva imagen a mi estructura porque devuelve la imagen como map[string]DynamoDBAttributeValue.
Puedo verificar la clave individual y luego asignarla a mi estructura una por una, pero ¿hay una manera directa de llegar a Marshall directamente?
func HandleRequest(ctx context.Context, event events.DynamoDBEvent) {
for _, record := range event.Records {
var newStruct models.MyStruct // want to marshall newImage in this struct
logger.Debugf("New: %#v", record.Change.NewImage)
}
}
ACTUALIZACIÓN:
Este es el evento DynamoDBEvent personalizado que estoy usando ahora:
type DynamoDBEvent struct {
Records []DynamoDBEventRecord `json:"Records"`
}
type DynamoDBEventRecord struct {
AWSRegion string `json:"awsRegion"`
Change DynamoDBStreamRecord `json:"dynamodb"`
EventID string `json:"eventID"`
EventName string `json:"eventName"`
EventSource string `json:"eventSource"`
EventVersion string `json:"eventVersion"`
EventSourceArn string `json:"eventSourceARN"`
UserIdentity *events.DynamoDBUserIdentity `json:"userIdentity,omitempty"`
}
type DynamoDBStreamRecord struct {
ApproximateCreationDateTime events.SecondsEpochTime `json:"ApproximateCreationDateTime,omitempty"`
Keys map[string]*dynamodb.AttributeValue `json:"Keys,omitempty"`
NewImage map[string]*dynamodb.AttributeValue `json:"NewImage,omitempty"`
OldImage map[string]*dynamodb.AttributeValue `json:"OldImage,omitempty"`
SequenceNumber string `json:"SequenceNumber"`
SizeBytes int64 `json:"SizeBytes"`
StreamViewType string `json:"StreamViewType"`
}
pude hacerlo escribiendo registros de eventos DynamoDBEvent personalizados
- shashank sachan
29/03/2021 a las 14:09
¿Podemos compartir algún código como respuesta para demostrar cómo utilizó DynamoDBEvent para resolver el problema? Esto podría resultar útil para futuros lectores.
- Jeremy Caney
29/03/2021 a las 18:12
Se agregó el evento personalizado
- Shashank Sachan
14 de abril de 2021 a las 12:41
------------------------------------
Desafortunadamente, todavía no existe una forma elegante, por lo que debe verificar cada par clave/valor y asignarlos a su estructura.
PD: como azúcar pequeña, puedes usar la función FromDynamoDBMap de este paquete y trabajar con map[string]interface{}, no con map[string]events.DynamoDBAttributeValue, que es mucho más fácil.
------------------------------------
He creado una solución para el problema. Esto fue crucial para mi implementación ya que mi implementación utiliza claves personalizadas.
Desafortunadamente, el tipo Número debe convertirse a Float64 paraasegúrese de que no se pierda.
Esto dará como resultado una estructura completamente utilizable contra el conjunto de cambios. Es posible que necesites un mapa de tus modelos y un campo conocido
Uso
newResult, _ := UnmarshalStreamImage(record.Change.NewImage)
newMarshal, _ := attributevalue.MarshalMap(newResult)
model := SomeModel{}
err := attributevalue.UnmarshalMap(newMarshal, &model)
Código de función
// UnmarshalStreamImage converts events.DynamoDBAttributeValue to struct
func UnmarshalStreamImage(attribute map[string]events.DynamoDBAttributeValue) (map[string]interface{}, error) {
baseAttrMap := make(map[string]interface{})
for k, v := range attribute {
baseAttrMap[k] = extractVal(v)
}
return baseAttrMap, nil
}
func extractVal(v events.DynamoDBAttributeValue) interface{} {
var val interface{}
switch v.DataType() {
case events.DataTypeString:
val = v.String()
case events.DataTypeNumber:
val, _ = v.Float()
case events.DataTypeBinary:
val = v.Binary()
case events.DataTypeBoolean:
val = v.Boolean()
case events.DataTypeNull:
val = nil
case events.DataTypeList:
list := make([]interface{}, len(v.List()))
for _, item := range v.List() {
list = append(list, extractVal(item))
}
val = list
case events.DataTypeMap:
mapAttr := make(map[string]interface{}, len(v.Map()))
for k, v := range v.Map() {
mapAttr[k] = extractVal(v)
}
val = mapAttr
case events.DataTypeBinarySet:
set := make([][]byte, len(v.BinarySet()))
for _, item := range v.BinarySet() {
set = append(set, item)
}
val = set
case events.DataTypeNumberSet:
set := make([]string, len(v.NumberSet()))
for _, item := range v.NumberSet() {
set = append(set, item)
}
val = set
case events.DataTypeStringSet:
set := make([]string, len(v.StringSet()))
for _, item := range v.StringSet() {
set = append(set, item)
}
val = set
}
return val
}```