简体   繁体   中英

How to post a JSON array to AWS Lambda through API Gateway? json: cannot unmarshal object into Go value of type []interface {}

This first example is non-problematic code:

You make a lambda out of this:

package main

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

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

func Handler(s interface{}) (interface{}, error) {
    return s, nil
}

When I go to the test section of lambda, I use this as my test:

{"id":"123"}

and that returns:

{"id":"123"}

Then I use this as the test in the lambda GUI:

[{"id":"123"}]

and that returns:

[{"id":"123"}]

I put that behind an API gateway, and send the same string:

curl https://69wisebmza.execute-api.us-east-1.amazonaws.com/default/simplestlambda -d '{"id":"123"}' --header "Content-Type: application/json"

That returns a response, the beginning of which is:

{"id":"123"}

so here's the problematic code - the only change is that it accepts and returns a slice of interfaces :

package main

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

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

func Handler(s []interface{}) ([]interface{}, error) {
    return s, nil
}

From the lambda GUI test console, I send:

[{"id":"123"}]

and receive back:

[{"id":"123"}]

From that same console, I send:

{"id":"123"}

and receive back this EXPECTED error:

{
  "errorMessage": "json: cannot unmarshal object into Go value of type []interface {}",
  "errorType": "UnmarshalTypeError"
}

So far so good.

Now, I put that behind an API gateway, and do this:

curl https://oz72tn566l.execute-api.us-east-1.amazonaws.com/default/simplestslice -d '[{"id":"123"}]' --header "Content-Type: application/json"

I get:

{"message":"Internal Server Error"}

The logs show this:

json: cannot unmarshal object into Go value of type []interface {}: UnmarshalTypeError
null

So I'm wondering why might this not be working?

When you proxy the request through some other AWS event source, the payload sent to the lambda gets wrapped into an event object.

In the case of API Gateway, the payload is a events.APIGatewayProxyRequest , which is not a slice, and can't be marshalled into a []interface{} .

The aws-lambda-go github repo has a piece of documentation that shows how to build the handler. In short:

func echoHandler(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    fmt.Println(request.Body) // prints [{"id":"123"}]
    return events.APIGatewayProxyResponse{Body: request.Body, StatusCode: 200}, nil
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM