0

I am following this post, so far the simple version is working but the section using AWS dynamodb is not working for me.

I have created an AWS dynamo table and inserted data

aws dynamodb create-table --table-name Services --attribute-definitions AttributeName=Name,AttributeType=S --key-schema AttributeName=Name,KeyType=HASH --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5
aws dynamodb put-item --table-name Services --item '{"Name": {"S": "Lets Keep Safe"}, "ID": {"N": "3"}, "CreatedAt":  {"S": "2020-11-21"}}'

main.go

package main

import (
    "github.com/aws/aws-lambda-go/lambda"
)

// Service Names
type Service struct {
    Name      string `json:"name"`
    ID        int    `json:"id"`
    CreatedAt string `json:"created_at"`
}

func show(ID string) (*Service, error) {
    // Fetch a specific book record from the DynamoDB database. We'll
    // make this more dynamic in the next section.
    // ser, err := getItem(ID)
    ser, err := getItem("2")
    if err != nil {
        return nil, err
    }

    return ser, nil
}

func main() {
    lambda.Start(show)
}

db.go

package main

import (
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/dynamodb"
    "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
)

// Declare a new DynamoDB instance. Note that this is safe for concurrent
// use.
var db = dynamodb.New(session.New(), aws.NewConfig().WithRegion("eu-west-1"))

func getItem(ID string) (*Service, error) {
    // Prepare the input for the query.
    input := &dynamodb.GetItemInput{
        TableName: aws.String("services"),
        Key: map[string]*dynamodb.AttributeValue{
            "ID": {
                N: aws.String(ID),
            },
        },
    }

    // Retrieve the item from DynamoDB. If no matching item is found
    // return nil.
    result, err := db.GetItem(input)
    if err != nil {
        return nil, err
    }
    if result.Item == nil {
        return nil, nil
    }

    // The result.Item object returned has the underlying type
    // map[string]*AttributeValue. We can use the UnmarshalMap helper
    // to parse this straight into the fields of a struct. Note:
    // UnmarshalListOfMaps also exists if you are working with multiple
    // items.
    ser := new(Service)
    err = dynamodbattribute.UnmarshalMap(result.Item, ser)
    if err != nil {
        return nil, err
    }

    return ser, nil
}

Invoking the lambda results in

{"errorMessage":"json: cannot unmarshal object into Go value of type string","errorType":"UnmarshalTypeError"}
0

1 Answer 1

1

working example based on the AWS dynamodb docs, the issue was it was attempting to unmarshal a null value, logging the output to cloudwatch caught this.

main.go

package main

import (
    "github.com/aws/aws-lambda-go/lambda"
    "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbiface"
)

var (
    dynaClient dynamodbiface.DynamoDBAPI
)

func show() (*[]Service, error) {

    ser, err := getAllServices("Services")
    if err != nil {
        return nil, err
    }

    return ser, nil
}

func main() {
    lambda.Start(show)
}

db.go

package main

import (
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/dynamodb"
    "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
    "github.com/aws/aws-sdk-go/service/dynamodb/expression"

    "fmt"
    "os"
)

// Service Names
type Service struct {
    Name      string `json:"name"`
    ID        int    `json:"id"`
    CreatedAt string `json:"created_at"`
}

var (
    sess = session.Must(session.NewSessionWithOptions(session.Options{
        SharedConfigState: session.SharedConfigEnable,
    }))

    // Create DynamoDB client
    svc = dynamodb.New(sess)
)

func getAllServices(tableName string) (*[]Service, error) {

    // Get back the title, year, and rating
    proj := expression.NamesList(expression.Name("Name"), expression.Name("ID"), expression.Name("CreatedAt"))

    expr, err := expression.NewBuilder().WithProjection(proj).Build()
    if err != nil {
        fmt.Println("Got error building expression:")
        fmt.Println(err.Error())
        os.Exit(1)
    }
    // snippet-end:[dynamodb.go.scan_items.expr]

    // snippet-start:[dynamodb.go.scan_items.call]
    // Build the query input parameters
    params := &dynamodb.ScanInput{
        ExpressionAttributeNames: expr.Names(),
        ProjectionExpression:     expr.Projection(),
        TableName:                aws.String(tableName),
    }

    // Make the DynamoDB Query API call
    result, err := svc.Scan(params)
    if err != nil {
        fmt.Println("Query API call failed:")
        fmt.Println((err.Error()))
        os.Exit(1)
    }

    item := new([]Service)
    err = dynamodbattribute.UnmarshalListOfMaps(result.Items, item)
    return item, nil

}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.