必须显式调用 ctx.ReadJSON() 且配置 app.Validator,结构体 json 标签和 binding 规则才生效;FormValue、URLParam 与 JSON 无关;重复读 Body 会 panic;四类参数来源完全隔离。

必须显式调用 ctx.ReadJSON(),结构体标签 + 全局 validator 才生效;不设 app.Validator,binding 标签完全被忽略。
ReadJSON 是唯一可靠入口,别碰 FormValue 或 URLParam
前端发的是 application/json,就只能走 ctx.ReadJSON(&v)。用 ctx.FormValue("field") 一定为空,因为 FormValue 只处理 application/x-www-form-urlencoded 和 multipart/form-data;ctx.URLParam() 更是只读 query string,跟请求体无关。
- 先确认 Content-Type:
ctx.Request().Header.Get("Content-Type")必须包含"application/json",否则ReadJSON会静默失败或报错 - 结构体字段必须带
json:"field_name"tag,否则字段永远绑定不上 - 不要在中间件里依赖自动绑定——Iris 的结构体自动注入(如
func(ctx iris.Context, u User))只在 controller handler 生效,中间件里必须手动ReadJSON
binding 标签要起作用,得先给 app 装 validator 实例
Iris 不自带校验器,binding:"required" 这类标签默认不触发。你得自己初始化一个 validator(比如 go-playground/validator/v10),再赋值给 app.Validator。
- 没设
app.Validator→ReadJSON成功但跳过所有binding规则,空字符串、非法邮箱都照单全收 -
binding:"email"要求字段非空且格式合法;binding:"gte=1,lte=100"对整数字段有效,但对字符串长度无效(得用min=1,max=100) - 错误必须手动处理:
if err != nil { ctx.StatusCode(400); ctx.JSON(err); return },Iris 不自动拦截
重复读 Body 会 panic:中间件里 ReadJSON 后,handler 别再调一次
ctx.Request().Body 是单次读取流,ReadJSON 内部已调用 io.ReadAll 消耗完它。如果中间件读了一次,后续 handler 还调 ReadJSON,就会报 http: read on closed response body。
- 解决方案只有两个:要么把参数解析逻辑统一收口到中间件(并调
ctx.StopExecution()阻断后续),要么全交给 handler 自己读 - 若需日志或鉴权用到 JSON 字段,建议中间件只读一次,把解析结果存进
ctx.Values().Set("parsed_body", &v),handler 里取出来复用 - 千万别用
ioutil.ReadAll或io.ReadAll手动读 Body 再传给json.Unmarshal——绕过 Iris 封装,失去 validator 绑定能力
最易被忽略的一点:路径参数、查询参数、表单字段、JSON 请求体,四者来源完全隔离,ctx.Params().Get() 永远拿不到 JSON 字段,ctx.FormValue() 永远读不了 {"id":123}。混用就丢数据,不是 bug,是设计如此。


















