Go-Swagger中如何自定义校验器并在Swagger规范中使用?
实现Go-Swagger自定义字符串格式校验器
要实现和strfmt.UUID、strfmt.ObjectId一致的自定义格式校验,需完成以下核心步骤:
1. 定义自定义格式类型并实现校验逻辑
创建底层为string的自定义类型,实现strfmt.Validator接口(要求实现Validate() error方法),同时实现序列化/反序列化接口确保数据处理正常:
package yourpackage import ( "github.com/go-openapi/strfmt" "github.com/go-openapi/swag" "github.com/hashicorp/go-multierror" "unicode" ) // Login 自定义登录名格式类型 type Login string // Validate 实现strfmt.Validator接口,调用自定义校验逻辑 func (l Login) Validate() error { return ValidateLogin(string(l)) } // MarshalText 实现序列化接口 func (l Login) MarshalText() ([]byte, error) { return []byte(l), nil } // UnmarshalText 实现反序列化接口,反序列化时自动触发校验 func (l *Login) UnmarshalText(data []byte) error { *l = Login(data) return l.Validate() } // Password 自定义密码格式类型 type Password string // Validate 实现strfmt.Validator接口 func (p Password) Validate() error { return ValidatePassword(string(p)) } // MarshalText 实现序列化接口 func (p Password) MarshalText() ([]byte, error) { return []byte(p), nil } // UnmarshalText 实现反序列化接口 func (p *Password) UnmarshalText(data []byte) error { *p = Password(data) return p.Validate() } // 自定义登录名校验函数 func ValidateLogin(s string) error { var err error if len(s) == 0 { err = multierr.Append(err, swag.RequiredError("login", "string")) } if len(s) < 8 { err = multierr.Append(err, swag.MinLengthError("login", 8, len(s))) } for _, r := range s { if !unicode.IsLetter(r) && !unicode.IsNumber(r) || r >= unicode.MaxASCII { err = multierr.Append(err, swag.InvalidTypeError("login", "alphanumeric ASCII", r)) } } return err } // 自定义密码校验函数 func ValidatePassword(pass string) error { var err error if len(pass) == 0 { err = multierr.Append(err, swag.RequiredError("password", "string")) } if len(pass) < 8 { err = multierr.Append(err, swag.MinLengthError("password", 8, len(pass))) } var upp, low, num, sym bool for _, char := range pass { switch { case unicode.IsUpper(char): upp = true case unicode.IsLower(char): low = true case unicode.IsNumber(char): num = true case unicode.IsPunct(char) || unicode.IsSymbol(char): sym = true default: err = multierr.Append(err, swag.InvalidTypeError("password", "upper/lower/number/symbol", char)) } } if !upp { err = multierr.Append(err, swag.RequiredError("password", "uppercase character")) } if !low { err = multierr.Append(err, swag.RequiredError("password", "lowercase character")) } if !num { err = multierr.Append(err, swag.RequiredError("password", "numeric character")) } if !sym { err = multierr.Append(err, swag.RequiredError("password", "symbol/punctuation character")) } return err }
2. 注册自定义格式到strfmt注册表
在程序启动阶段(比如init()函数),将自定义格式注册到strfmt.Default注册表,让go-swagger的校验器能识别这些格式:
package yourpackage import "github.com/go-openapi/strfmt" func init() { // 注册login格式,关联到Login类型 strfmt.Default.Add("login", func() strfmt.Formatter { return new(Login) }) // 注册password格式,关联到Password类型 strfmt.Default.Add("password", func() strfmt.Formatter { return new(Password) }) }
3. 配置Swagger规范
在Swagger YAML/JSON中直接使用自定义format字段,名称需和注册的格式名一致:
components: schemas: Credentials: type: object properties: login: type: string format: login password: type: string format: password required: [login, password]
4. 生成代码时关联自定义类型
使用swagger generate server/client命令生成代码时,通过两种方式关联自定义类型:
方式1:命令行参数指定模型包
swagger generate server -f swagger.yml --model-package yourpackage/models
方式2:Swagger规范中添加x-go-type扩展
如果自定义类型不在默认生成的模型包中,可在schema里明确指定:
login: type: string format: login x-go-type: type: Login import: package: yourpackage
5. 验证效果
代码生成后,API接收请求时会自动将login、password字段反序列化为自定义类型,并触发Validate()方法执行校验逻辑。校验不通过时,会返回标准的API错误响应。
内容的提问来源于stack exchange,提问作者fpawel
相关产品推荐
相关产品推荐

