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

huangapple go评论99阅读模式
英文:

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

问题

这是一个非问题代码的示例:

你可以将其转换为lambda函数:

package main

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

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

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

当我进入lambda的测试部分时,我使用以下内容作为我的测试:

{"id":"123"}

返回结果为:

{"id":"123"}

然后我在lambda的GUI中使用以下内容作为测试:

[{"id":"123"}]

返回结果为:

[{"id":"123"}]

我将其放在API网关后,并发送相同的字符串:

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

返回一个响应,其开头为:

{"id":"123"}

现在,这是有问题的代码-唯一的更改是它接受并返回一个接口切片

package main

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

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

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

从lambda的GUI测试控制台,我发送:

[{"id":"123"}]

并收到以下返回结果:

[{"id":"123"}]

从同一个控制台,我发送:

{"id":"123"}

并收到这个预期的错误:

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

到目前为止都很好。

现在,我将其放在API网关后,并执行以下操作:

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

我得到:

{"message":"Internal Server Error"}

日志显示如下:

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

所以我想知道为什么它可能不起作用?

英文:

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?

答案1

得分: 2

当您通过其他AWS事件源代理请求时,发送到Lambda的有效负载将被包装成一个事件对象。

在API Gateway的情况下,有效负载是一个events.APIGatewayProxyRequest,它不是一个切片,不能被编组为[]interface{}

aws-lambda-go GitHub仓库有一篇文档,展示了如何构建处理程序。简而言之:

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

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
}

huangapple
  • 本文由 发表于 2021年8月13日 19:44:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/68771732.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定