revel中解析post json需用json.newdecoder(c.request.body)直接流式解码,禁用c.params.get或parseform;类型须严格匹配,显式关闭body,检查错误并设400状态码。

Revel 中如何正确解析 POST 的 JSON Body
别用 c.Params.Get 或 c.Request.PostForm 去读 JSON,它们只处理表单编码(application/x-www-form-urlencoded)或查询参数。JSON 必须从 c.Request.Body 流中手动解码。
- 必须在首次调用
json.NewDecoder前确保没调用过ioutil.ReadAll或c.Request.ParseForm()—— 否则 Body 已被读空,Decode()会静默失败或返回EOF - 目标变量类型要和 JSON 结构严格匹配:发送
["a","b"]就用[]string;发送{"id":1,"name":"x"}就得定义 struct 或map[string]interface{} - 记得加
defer c.Request.Body.Close():虽然 Revel 通常会回收连接,但不显式关闭可能在高并发下触发连接泄漏或复用异常 - 错误必须检查并返回明确状态码,例如
c.Response.Status = 400,不能只打日志后继续执行
Revel 中如何返回结构化 JSON 响应
直接调用 c.RenderJSON() 即可,它内部调用 json.Marshal,不需要自己序列化再包装。
-
c.RenderJSON(data)自动设置Content-Type: application/json和状态码200 OK,无需手动设c.Response.ContentType - 如果需要自定义状态码(比如创建成功返回
201 Created),在调用前改c.Response.Status即可,c.RenderJSON()不会覆盖它 - 若启用了
results.pretty=true(在conf/app.conf中),输出会自动带缩进,适合调试;生产环境建议关掉以减少体积 - 避免把
bytes或已编码的字符串传给c.RenderJSON()—— 它会再套一层 JSON 编码,导致响应变成"{\"key\":\"val\"}"这种双引号包裹的字符串
常见错误现象与对应原因
遇到返回乱码、空数组、Base64 字符串或 400 错误,大概率是下面这几个点之一出了问题:
- curl 发送了 JSON 但 header 漏了
-H "Content-Type: application/json"→ Revel 默认按表单解析,Body 被忽略,Decode()读到空流 → 报invalid character 'x' looking for beginning of value - 控制器里先写了
c.Request.ParseForm()再尝试json.Decode()→ Body 已耗尽 →Decode()返回io.EOF或静默得到零值 - 前端发的是对象
{"name":"x"},代码却声明var data []string→ 解码失败,data保持空切片,没报错但逻辑异常 - 返回时用了
c.RenderText(string(b))而非c.RenderJSON(v)→ 响应体是纯文本,Content-Type是text/plain,前端response.json()会抛错
测试时 curl 命令怎么写才可靠
别依赖浏览器地址栏或表单提交测 JSON 接口,用 curl 控制最稳。
- POST JSON 必须带
-H "Content-Type: application/json",否则服务端收不到有效 Body - 数据用单引号包裹,避免 shell 解析双引号内的变量,例如:
-d'{"id":123}',而不是-d"{"id":123}" - 加
-v查看完整请求/响应头,确认状态码、Content-Type 和实际响应体 - 如果返回异常,先用
curl -i看状态码和头,再结合日志里revel.INFO.Printf输出比对原始data值











