将map [string] DynamoDBAttributeValue解组成一个struct

And*_*M16 10 go amazon-dynamodb aws-lambda aws-sdk-go

我正在尝试使用aws-sdk-go设置AWS-lambda ,只要将新user内容添加到某个dynamodb表,就会触发该事务.

一切都工作得很好,但我找不到解组地图的方法,map[string]DynamoDBAttributeValue如:

{
    "name": {
        "S" : "John"
    },
    "residence_address": {
        "M": {
            "address": {
                "S": "some place"
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

对于给定的结构,例如,User结构.这里显示了一个map[string]*dynamodb.AttributeValue将一个unmarhaling 到一个给定接口的例子,但我找不到一种方法来做同样的事情,map[string]DynamoDBAttributeValue即使这些类型似乎适合相同的目的.

map[string]DynamoDBAttributeValueevents.DynamoDBEvents从包中返回github.com/aws/aws-lambda-go/events.这是我的代码:

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)
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

当然,我可以编组record.Change.NewImageJSON并将其解组回给定的结构,但是,我必须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
}
Run Code Online (Sandbox Code Playgroud)

然后简单地使用dynamodbattribute.UnmarshalMap,但在events.DataTypeMap它上面将是一个非常棘手的过程.

有没有一种方法可以解析一个DynamoDB记录来自events.DynamoDBEvent一个结构,并显示类似的方法map[string]*dynamodb.AttributeValue

Sky*_*.Li 12

我尝试了你提供的函数,但遇到了一些问题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)

}
Run Code Online (Sandbox Code Playgroud)


小智 9

我很沮丧,记录中的 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"`
}
Run Code Online (Sandbox Code Playgroud)