英文:
AWS Lambda golang json body parsing
问题
当使用AWS Lambda(通过AWS控制台访问)运行测试事件时,我能够传入以下请求体并正确解析数据到自定义结构体。
自定义结构体:
type ContactForm struct {
Phone int `json:"phone"`
Email string `json:"email"`
Business string `json:"business"`
Message string `json:"message"`
Name string `json:"name"`
File_data *string `json:"file_data"`
File_name *string `json:"file_name"`
Uri *string
}
事件JSON:
{
"email": "email.com",
"phone": 80077777,
"business": "business",
"message": "message",
"name": "name"
}
当尝试通过Postman或XHR请求命中Lambda函数的函数URL时,解析后的请求体默认为nil、0和空字符串值,显示无法读取JSON请求体。这是Golang Lambda的入口点,应该传入该对象,但通过函数URL执行时失败。
func HandleRequest(ctx context.Context, contactForm ContactForm) {
if contactForm.File_data != nil && contactForm.File_name != nil {
uri := create_file(*contactForm.File_data, *contactForm.File_name)
contactForm.Uri = &uri
}
fmt.Printf("%v", contactForm)
body := create_email_body(contactForm)
sendEmail(contactForm.Business, body)
}
在通过端点解析时,是否需要进行其他逻辑以与使用测试事件时相比?
英文:
When running a test event with AWS Lambda (accessed via AWS Console) I am able to pass in the following body and properly parse the data to a custom struct
Custom struct:
type ContactForm struct {
Phone int `json:"phone"`
Email string `json:"email"`
Business string `json:"business"`
Message string `json:"message"`
Name string `json:"name"`
File_data *string `json:"file_data"`
File_name *string `json:"file_name"`
Uri *string
}
Event JSON:
{
"email": "email.com",
"phone": 80077777,
"business": "business",
"message": "message",
"name": "name"
}
When attempting to hit the lambda via a function URL using postman or an XHR request the body when parsed defaults to nil, 0, and empty string values showing that it is not able to read the json body. This is the entry point of the golang lambda that should pass in the object, but fails when done via function URL
func HandleRequest(ctx context.Context, contactForm ContactForm) {
if contactForm.File_data != nil && contactForm.File_name != nil {
uri := create_file(*contactForm.File_data, *contactForm.File_name)
contactForm.Uri = &uri
}
fmt.Printf("%v", contactForm)
body := create_email_body(contactForm)
sendEmail(contactForm.Business, body)
}
Is there additional logic that needs to be done when parsing via an endpoint in comparison to using a Test Event?
答案1
得分: 2
根据你将数据发送到函数的方式(例如ApiGatewayProxyRequest或在你的情况下的LambdaFunctionURLRequest),事件可能包含额外的字段和元数据。我建议你记录原始事件,参考https://docs.aws.amazon.com/lambda/latest/dg/golang-logging.html,并根据实际发送到函数的内容来定义你的结构体。当我遇到类似情况时,就是这种情况。
此外,你可以使用预定义的包来定义你的事件:"github.com/aws/aws-lambda-go/events"。我认为events.LambdaFunctionURLRequest是你在处理程序中需要设置的内容。然后你可以解析这个负载的正文中的JSON。参考https://pkg.go.dev/github.com/aws/aws-lambda-go/events#LambdaFunctionURLRequest。
func HandleRequest(ctx context.Context, event events.LambdaFunctionURLRequest) {
body := []byte(event.Body)
var contact ContactForm
json.Unmarshal(body, &contact)
log.Printf("%v", contact.Email)
}
以下是来自GoPlayground的相同方法/逻辑。
package main
import (
"encoding/json"
"fmt"
)
type ContactForm struct {
Phone int `json:"phone"`
Email string `json:"email"`
Business string `json:"business"`
Message string `json:"message"`
Name string `json:"name"`
File_data *string `json:"file_data"`
File_name *string `json:"file_name"`
Uri *string
}
func main() {
input := []byte(`{"email": "email.com","phone": 80077777,"business": "programming","message": "hello world","name": "John Doe"}`)
var contact ContactForm
json.Unmarshal(input, &contact)
fmt.Printf("%v", contact.Email)
}
你需要对数据进行一些验证,以确保它实际上是JSON,或者捕获负载不正确的情况。这在一般的编程中是很好的做法,所以我假设你还会处理正文无法序列化为结构体的边缘情况。
英文:
So depending on how you're posting the data to the function e.g ApiGatewayProxyRequest or in your case LambdaFunctionURLRequest, the event might contain extra fields and metadata. I'd suggest you log the raw event, see https://docs.aws.amazon.com/lambda/latest/dg/golang-logging.html and base your struct off of what you see actually posted to the function. This was the case when I've run into circumstances like yours.
Also, there is a predefined package you can use to define your events: "github.com/aws/aws-lambda-go/events". I think events.LambdaFunctionURLRequest is what you need to set in your handler. Then you can parse the JSON from the body of this payload. See https://pkg.go.dev/github.com/aws/aws-lambda-go/events#LambdaFunctionURLRequest.
func HandleRequest(ctx context.Context, event events.LambdaFunctionURLRequest) {
body := []byte(event.Body)
var contact ContactForm
json.Unmarshal(body, &contact)
log.Printf("%v", contact.Email)
}
Here is the same method/logic from GoPlayground.
package main
import (
"encoding/json"
"fmt"
)
type ContactForm struct {
Phone int `json:"phone"`
Email string `json:"email"`
Business string `json:"business"`
Message string `json:"message"`
Name string `json:"name"`
File_data *string `json:"file_data"`
File_name *string `json:"file_name"`
Uri *string
}
func main() {
input := []byte(`{"email": "email.com","phone": 80077777,"business": "programming","message": "hello world","name": "John Doe"}`)
var contact ContactForm
json.Unmarshal(input, &contact)
fmt.Printf("%v", contact.Email)
}
You'll need to do some validation of the data to make sure it's actually json or catch the cases in which the payload is bad. This is good programming in general, so I'm assuming you'd additionally deal with edge cases in which the body didn't serialize into the struct.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论