Beego不会自动解析JSON请求体,必须手动读取RequestBody并用json.Unmarshal解析;GetString仅处理URL查询参数和表单数据,不读取JSON字段。

Beego 不会自动解析请求体里的 JSON,必须手动读取 RequestBody 并用 json.Unmarshal 解析;否则拿到的是空结构体或 panic。
为什么 this.GetString("xxx") 拿不到 JSON 字段
因为 GetString 等方法只读取 URL 查询参数(?key=value)和表单数据(application/x-www-form-urlencoded),不处理 application/json 请求体。JSON 数据始终在 this.Ctx.Input.RequestBody 里,原样是 []byte。
- 常见错误:POST JSON 时仍写
name := this.GetString("name")→ 返回空字符串,且无报错提示 - 即使请求头带
Content-Type: application/json,Beego 也不会自动触发解析 - 若未在
app.conf中设置copyrequestbody = true,RequestBody可能为空(尤其在用了中间件或重定向后)
接收 JSON 的标准写法(含错误处理)
直接读 RequestBody,用 json.Unmarshal 绑定到结构体,必须检查 err:
func (c *UserController) Post() {
var user struct {
ID int `json:"id"`
Name string `json:"name"`
Pwd string `json:"pwd"`
}
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &user); err != nil {
c.Ctx.ResponseWriter.WriteHeader(400)
c.Ctx.WriteString("invalid JSON: " + err.Error())
return
}
// 此时 user 已填充,可继续业务逻辑
c.Data["json"] = map[string]interface{}{"ok": true, "id": user.ID}
c.ServeJSON(false)
}
- 结构体字段名必须首字母大写(导出),否则
json包无法赋值 - 推荐用匿名 struct 或定义明确的类型,避免误用全局变量
- 不要忽略
err:JSON 字段缺失、类型错(如传字符串给 int)、嵌套格式错都会进err -
c.Ctx.Input.RequestBody是一次性读取,重复调用可能返回空 slice
接收 JSON 后怎么安全返回响应
别手写 json.Marshal + WriteString,用框架内置的 ServeJSON:
-
c.Data["json"] = data设置响应内容(支持map、struct、slice) - 立刻调
c.ServeJSON(false)(生产环境设为false,禁用缩进) - 若需非 200 状态码,先调
c.Ctx.ResponseWriter.WriteHeader(401),再ServeJSON - 切忌在
ServeJSON后还调c.Redirect或c.TplName,会 panic - 如需返回原始 HTML 字符串(含
、>),在app.conf加JSONEscapeHTML = false
容易被忽略的配置和边界情况
app.conf 里这行不是可选的:
copyrequestbody = true
- 默认为
false,意味着RequestBody在某些场景下(比如用了Filter或Router链路中多次读取)会变空 - 设为
true后,Beego 会在请求开始时缓存一份完整 body,确保RequestBody始终可用 - 不配这一项,本地调试可能正常,上线后偶发空 body,极难复现
- 如果同时要支持表单和 JSON,得自己判断
Content-Type头,再分流处理——Beego 不自动做 content-negotiation











