Go验证:复用结构体时如何禁止JSON请求体包含指定字段?
解决方案:通过自定义验证规则实现POST请求禁止ID字段
常用的go-playground/validator包本身没有现成的"禁止字段出现"标签,但可以自定义验证规则来实现,完全契合你要的结构体标签方式,且不影响结构体复用。
步骤1:扩展validator自定义验证规则
先安装validator包:
go get github.com/go-playground/validator/v10
编写自定义验证函数,用于检查字段是否被传入了非零值(即禁止该字段出现在请求体中):
import "github.com/go-playground/validator/v10" // ForbiddenField 验证字段是否被禁止传入请求体 func ForbiddenField(fl validator.FieldLevel) bool { // 针对string类型的ID,判断是否为空字符串(零值) return fl.Field().String() == "" }
步骤2:注册自定义验证器
在项目初始化时注册这个规则,自定义标签名为forbidden:
var validate *validator.Validate func init() { validate = validator.New() // 注册自定义验证规则 err := validate.RegisterValidation("forbidden", ForbiddenField) if err != nil { panic(err) } }
步骤3:修改结构体标签
给ID字段添加自定义validate:"forbidden"标签,保留原有JSON、Firestore标签不影响GET请求复用:
type Student struct { ID string `json:"id" firestore:"id" validate:"forbidden"` Name string `json:"name" validate:"required" firestore:"name"` }
步骤4:POST请求中执行验证
处理POST请求时,绑定请求体后执行验证,捕获错误并返回自定义提示:
import ( "encoding/json" "fmt" "net/http" ) func handlePostStudent(w http.ResponseWriter, r *http.Request) { var student Student if err := json.NewDecoder(r.Body).Decode(&student); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // 执行结构体验证 if err := validate.Struct(student); err != nil { // 遍历验证错误,返回自定义提示 for _, fieldErr := range err.(validator.ValidationErrors) { if fieldErr.Tag() == "forbidden" { http.Error(w, fmt.Sprintf("%s字段不允许出现在POST请求体中", fieldErr.Field()), http.StatusBadRequest) return } } http.Error(w, err.Error(), http.StatusBadRequest) return } // 后续业务逻辑处理... }
GET请求的复用处理
GET请求时,可通过StructExcept方法跳过ID字段的forbidden验证规则:
// GET请求验证时跳过ID字段的禁止规则 if err := validate.StructExcept(student, "ID"); err != nil { // 处理其他字段验证错误 }
备选方案:结构体嵌入拆分
如果觉得自定义验证过于繁琐,也可通过结构体嵌入拆分场景,既复用公共字段又区分请求类型:
// 基础公共结构体 type BaseStudent struct { Name string `json:"name" validate:"required" firestore:"name"` } // POST专用结构体(不含ID字段) type PostStudent struct { BaseStudent } // GET专用结构体(包含ID字段) type GetStudent struct { BaseStudent ID string `json:"id" firestore:"id"` }
内容的提问来源于stack exchange,提问作者Sid P Tkf
相关产品推荐
相关产品推荐

