将 map[string]DynamoDBAttributeValue 解组为结构
Unmarshal map[string]DynamoDBAttributeValue into a struct
我正在尝试使用 aws-sdk-go that is triggered whenever a new user
is added to a certain dynamodb table.
设置 AWS-lambda
一切正常,但我找不到解组地图 map[string]DynamoDBAttributeValue
的方法,例如:
{
"name": {
"S" : "John"
},
"residence_address": {
"M": {
"address": {
"S": "some place"
}
}
}
}
给定结构,例如 User
结构。 Here 显示了一个将 map[string]*dynamodb.AttributeValue
解组到给定接口的示例,但我找不到用 map[string]DynamoDBAttributeValue
做同样事情的方法,即使这些类型似乎适合相同目的。
map[string]DynamoDBAttributeValue
由包 github.com/aws/aws-lambda-go/events
中的 events.DynamoDBEvents
返回。这是我的代码:
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)
}
}
}
当然,我可以将 record.Change.NewImage
编组为 JSON 并将其解编回给定的结构,但是之后,我将不得不从后者开始手动初始化 dynamoUser
属性一个。
或者我什至可以编写一个将 map[string]DynamoDBAttributeValue
解析为 map[string]*dynamodb.AttributeValue
的函数,例如:
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
}
然后简单地使用 dynamodbattribute.UnmarshalMap
,但是在 events.DataTypeMap
上这将是一个非常棘手的过程。
有没有一种方法可以将来自 events.DynamoDBEvent
的 DynamoDB 记录解组到结构中,并使用与 map[string]*dynamodb.AttributeValue
所示的类似方法?
我尝试了您提供的函数,但在使用 events.DataTypeList
时遇到了一些问题,因此我设法编写了以下函数来解决问题:
// 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)
}
我很沮丧,因为记录中的 NewImage 类型不是 map[string]*dynamodb.AttributeValue,所以我可以使用 dynamodbattribute 包。
events.DynamoDBAttributeValue 的 JSON 表示似乎与 dynamodb.AttributeValue 的 JSON 表示相同。
所以我尝试创建自己的 DynamoDBEvent 类型并更改了 OldImage 和 NewImage 的类型,因此它将被编组到 map[string]*dynamodb.AttributeValue 而不是 map[string]events.DynamoDBAttributeValue
有点难看,但对我有用。
package main
import (
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
"fmt"
)
func main() {
lambda.Start(lambdaHandler)
}
// changed type of event from: events.DynamoDBEvent to DynamoDBEvent (see below)
func lambdaHandler(event DynamoDBEvent) error {
for _, record := range event.Records {
change := record.Change
newImage := change.NewImage // now of type: map[string]*dynamodb.AttributeValue
var item IdOnly
err := dynamodbattribute.UnmarshalMap(newImage, &item)
if err != nil {
return err
}
fmt.Println(item.Id)
}
return nil
}
type IdOnly struct {
Id string `json:"id"`
}
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"`
// changed to map[string]*dynamodb.AttributeValue
Keys map[string]*dynamodb.AttributeValue `json:"Keys,omitempty"`
// changed to map[string]*dynamodb.AttributeValue
NewImage map[string]*dynamodb.AttributeValue `json:"NewImage,omitempty"`
// changed to map[string]*dynamodb.AttributeValue
OldImage map[string]*dynamodb.AttributeValue `json:"OldImage,omitempty"`
SequenceNumber string `json:"SequenceNumber"`
SizeBytes int64 `json:"SizeBytes"`
StreamViewType string `json:"StreamViewType"`
}
我正在尝试使用 aws-sdk-go that is triggered whenever a new user
is added to a certain dynamodb table.
一切正常,但我找不到解组地图 map[string]DynamoDBAttributeValue
的方法,例如:
{
"name": {
"S" : "John"
},
"residence_address": {
"M": {
"address": {
"S": "some place"
}
}
}
}
给定结构,例如 User
结构。 Here 显示了一个将 map[string]*dynamodb.AttributeValue
解组到给定接口的示例,但我找不到用 map[string]DynamoDBAttributeValue
做同样事情的方法,即使这些类型似乎适合相同目的。
map[string]DynamoDBAttributeValue
由包 github.com/aws/aws-lambda-go/events
中的 events.DynamoDBEvents
返回。这是我的代码:
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)
}
}
}
当然,我可以将 record.Change.NewImage
编组为 JSON 并将其解编回给定的结构,但是之后,我将不得不从后者开始手动初始化 dynamoUser
属性一个。
或者我什至可以编写一个将 map[string]DynamoDBAttributeValue
解析为 map[string]*dynamodb.AttributeValue
的函数,例如:
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
}
然后简单地使用 dynamodbattribute.UnmarshalMap
,但是在 events.DataTypeMap
上这将是一个非常棘手的过程。
有没有一种方法可以将来自 events.DynamoDBEvent
的 DynamoDB 记录解组到结构中,并使用与 map[string]*dynamodb.AttributeValue
所示的类似方法?
我尝试了您提供的函数,但在使用 events.DataTypeList
时遇到了一些问题,因此我设法编写了以下函数来解决问题:
// 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)
}
我很沮丧,因为记录中的 NewImage 类型不是 map[string]*dynamodb.AttributeValue,所以我可以使用 dynamodbattribute 包。
events.DynamoDBAttributeValue 的 JSON 表示似乎与 dynamodb.AttributeValue 的 JSON 表示相同。
所以我尝试创建自己的 DynamoDBEvent 类型并更改了 OldImage 和 NewImage 的类型,因此它将被编组到 map[string]*dynamodb.AttributeValue 而不是 map[string]events.DynamoDBAttributeValue
有点难看,但对我有用。
package main
import (
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
"fmt"
)
func main() {
lambda.Start(lambdaHandler)
}
// changed type of event from: events.DynamoDBEvent to DynamoDBEvent (see below)
func lambdaHandler(event DynamoDBEvent) error {
for _, record := range event.Records {
change := record.Change
newImage := change.NewImage // now of type: map[string]*dynamodb.AttributeValue
var item IdOnly
err := dynamodbattribute.UnmarshalMap(newImage, &item)
if err != nil {
return err
}
fmt.Println(item.Id)
}
return nil
}
type IdOnly struct {
Id string `json:"id"`
}
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"`
// changed to map[string]*dynamodb.AttributeValue
Keys map[string]*dynamodb.AttributeValue `json:"Keys,omitempty"`
// changed to map[string]*dynamodb.AttributeValue
NewImage map[string]*dynamodb.AttributeValue `json:"NewImage,omitempty"`
// changed to map[string]*dynamodb.AttributeValue
OldImage map[string]*dynamodb.AttributeValue `json:"OldImage,omitempty"`
SequenceNumber string `json:"SequenceNumber"`
SizeBytes int64 `json:"SizeBytes"`
StreamViewType string `json:"StreamViewType"`
}