Go SDK调用Go编写的AWS Lambda时Payload解析失败排查
看起来你遇到的是典型的「本地SDK发送的Payload格式和控制台测试的不一致」问题,结合报错invalid character ')' after top-level value,咱们一步步来排查和解决:
核心问题分析
这个JSON解析错误明确告诉你:Lambda收到的Payload里多了一个多余的),导致JSON格式无效。但你把结构体输出到文件后用控制台测试正常,说明结构体本身序列化后的JSON是正确的,问题出在Go SDK发送Payload的过程中——肯定是发送时不小心给Payload加了额外字符,或者用错了序列化方式。
一步步排查&解决
1. 先抓出客户端实际发送的Payload
在你的Go客户端代码里,序列化完RedisBatch结构体后,立刻打印出完整的Payload字符串,对比控制台测试用的内容:
batch := RedisBatch{/* 你的结构体数据 */} payload, err := json.Marshal(batch) if err != nil { log.Fatalf("序列化失败: %v", err) } // 关键:打印实际发送的内容 log.Printf("即将发送的Payload: %s", string(payload))
同时,在Lambda函数的最开头,先打印收到的原始Payload,确认和客户端发送的是否一致:
func Handler(ctx context.Context, rawPayload []byte) (string, error) { // 打印Lambda实际收到的原始内容 log.Printf("Lambda收到的原始Payload: %s", string(rawPayload)) var batch RedisBatch err := json.Unmarshal(rawPayload, &batch) if err != nil { return "", fmt.Errorf("解析Payload失败: %v", err) } // 后续业务逻辑... }
这一步能直接帮你定位:是不是客户端发送的Payload里真的多了),或者有其他格式差异。
2. 确保用正确的方式序列化结构体
绝对不要用fmt.Sprintf或者直接转字符串的方式生成JSON,必须用encoding/json的Marshal方法,并且一定要处理序列化错误:
// 正确的序列化方式 payload, err := json.Marshal(redisBatch) if err != nil { // 序列化失败时直接终止,避免发送无效内容 log.Fatalf("无法序列化RedisBatch: %v", err) }
常见错误场景:有人图省事用fmt.Sprintf("%v", redisBatch)生成字符串,这得到的是Go结构体的打印格式(比如{Keys:[key1 key2]}),根本不是JSON,自然会触发解析错误。
3. 检查是否不小心修改了Payload
排查客户端代码里有没有在序列化后,对payload字节数组做额外操作:比如拼接字符串、添加括号、换行符等。举个典型的错误示例:
// 错误!不要这么做! payloadStr := fmt.Sprintf("(%s)", string(payload)) payload = []byte(payloadStr)
这种操作会给JSON前后加上括号,直接导致Lambda解析时遇到多余的),正好匹配你的报错。
4. 确认Lambda的输入类型匹配
如果你的Lambda函数直接用RedisBatch作为输入参数(比如func Handler(ctx context.Context, batch RedisBatch)),AWS的Go Runtime会自动帮你反序列化,但前提是Payload必须是标准JSON。如果客户端发送的内容格式不对,Runtime就会抛出类似的语法错误。
总结
根据你的描述,最可能的原因就是客户端在发送前给Payload多加了)字符,或者用了错误的序列化方式。通过打印客户端发送的内容和Lambda接收的原始内容,就能快速定位问题所在。
内容的提问来源于stack exchange,提问作者lightweight

