Gin框架POST请求传对象数组时遇JSON输入意外结束错误
首先咱们先梳理代码里的问题,再一步步搞定JSON数组的接收报错:
1. 先修正函数的语法错误
你的Receive函数定义是func Receive(c *gin.Context),但函数里写了return nil, err——这会直接导致编译失败,因为函数没声明返回值。你可以调整函数签名,比如改成返回error:
func Receive(c *gin.Context) error { // 后续代码... }
如果不需要返回值,应该用Gin的上下文方法终止请求并返回错误,比如c.AbortWithStatusJSON(http.StatusBadRequest, err.Error()),而不是直接return nil, err。
2. JSON数组接收报错的根源与解决
出现"unexpected end of JSON input"的常见原因是请求体被提前读取/消费,导致GetRawData()无法获取完整数据。比如你的路由中如果用了gin.BindJSON之类的绑定方法,或者有中间件尝试解析JSON对象(数组不符合对象格式,解析失败后没重置请求体),都会导致后续GetRawData()读取到空数据。
解决方法很直接:在调用GetRawData()读取完数据后,把请求体重新放回Context,确保数据流能被后续操作(如果有的话)正常读取,同时正确处理字节数组的日志打印:
import ( "bytes" "github.com/gin-gonic/gin" "io/ioutil" "log" ) func Receive(c *gin.Context) { // 读取原始请求体 rawData, err := c.GetRawData() if err != nil { c.AbortWithStatusJSON(400, gin.H{"error": err.Error()}) return } // 把读取后的字节流重新放回请求体,避免后续操作无法读取 c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(rawData)) // 打印原始数据时转成字符串,方便查看实际内容 log.Info("Raw data received - ", string(rawData)) // 如果需要解析JSON数组,可以在这里处理 // var data []map[string]string // if err := json.Unmarshal(rawData, &data); err != nil { // c.AbortWithStatusJSON(400, gin.H{"error": "invalid JSON array"}) // return // } }
这样修改后,不管是传入单个JSON对象{"key":"value"}还是JSON数组[{"key":"val"},{"key": "val"}],都能正常读取原始数据,不会再出现"unexpected end of JSON input"错误。
另外补充个小技巧:如果你只是需要解析JSON数组,其实可以直接用Gin的ShouldBindJSON方法绑定到切片类型,写法更简洁:
func Receive(c *gin.Context) { var data []map[string]string if err := c.ShouldBindJSON(&data); err != nil { c.AbortWithStatusJSON(400, gin.H{"error": err.Error()}) return } log.Info("Parsed data: ", data) }
内容的提问来源于stack exchange,提问作者skywalker2909

