Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the practical skills of parameter verification in golang validator library

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)05/31 Report--

Most people do not understand the knowledge points of this article "practical skills for checking parameters of golang validator library", so the editor summarizes the following contents, detailed contents, clear steps, and has a certain reference value. I hope you can get something after reading this article. Let's take a look at this article, "what practical skills for checking parameters of golang validator library have?"

Some practical skills of Parameter Calibration in validator Library

An inevitable step in web development is to check the request parameters. Usually we define the model (structure) corresponding to the request parameters in the code, and quickly parse the request parameters with the help of model binding, such as Bind and ShouldBind series methods in the gin framework.

The gin framework uses github.com/go-playground/validator for parameter verification. Github.com/go-playground/validator/v10 is already supported. We need to use binding tag to identify the relevant verification rules when defining the structure. You can check the validator document to see all the supported tag.

Basic example

First, let's take a look at the basic example of a built-in gin framework that uses validator for parameter verification.

Package mainimport ("net/http"github.com/gin-gonic/gin") type SignUpParam struct {Age uint8 `json: "age" binding: "gte=1,lte=130" `Name string `json: "name" binding: "required" `Email string `json: "email" binding: "required,email" `Password string `json: "password" binding: "required" `RePassword string `json: "re_password" binding: "required" Eqfield=Password "`} func main () {r: = gin.Default () r.POST (" / signup ", func (c * gin.Context) {var u SignUpParam if err: = c.ShouldBind (& u) Err! = nil {c.JSON (http.StatusOK, gin.H {"msg": err.Error (),}) return} / / saves business logic codes such as storage. C.JSON (http.StatusOK, "success")}) _ = r.Run (": 8999")}

Let's use curl to send a POST request to test:

Curl-H "Content-type: application/json"-X POST-d'{"name": "q1mi", "age": 18, "email": "123.com"} 'http://127.0.0.1:8999/signup

Output result:

{"msg": "Key: 'SignUpParam.Email' Error:Field validation for' Email' failed on the 'email' tag\ nKey:' SignUpParam.Password' Error:Field validation for 'Password' failed on the' required' tag\ nKey: 'SignUpParam.RePassword' Error:Field validation for' RePassword' failed on the 'required' tag"}

From the final output, you can see that the validator check is valid, but the field of the error prompt is not particularly friendly, and we may need to translate it into Chinese.

Translation check error message

The validator library itself supports internationalization, and the automatic translation of verification error messages can be realized with the help of the corresponding language pack. The following sample code demonstrates how to translate error messages into Chinese and into other languages in a similar way.

Package mainimport ("fmt", "net/http", "github.com/gin-gonic/gin", "github.com/gin-gonic/gin/binding", "github.com/go-playground/locales/en", "github.com/go-playground/locales/zh" ut "github.com/go-playground/universal-translator"github.com/go-playground/validator/v10" EnTranslations "github.com/go-playground/validator/v10/translations/en" zhTranslations "github.com/go-playground/validator/v10/translations/zh") / / define a global translator Tvar trans ut.Translator// InitTrans initialization translator func InitTrans (locale string) (err error) {/ / modify the Validator engine properties in the gin framework Implement custom if v, ok: = binding.Validator.Engine (). (* validator.Validate) Ok {zhT: = zh.New () / / Chinese translator enT: = en.New () / / English translator / / the first parameter is the fallback locale / / the following parameter is the locale that should be supported (multiple are supported) / / uni: = ut.New (zhT) ZhT) is also possible uni: = ut.New (enT, zhT, enT) / / locale usually depends on the 'Accept-Language' var ok bool / /' of the http request header and can also use uni.FindTranslator (...) Pass in multiple locale to find trans, ok = uni.GetTranslator (locale) if! ok {return fmt.Errorf ("uni.GetTranslator (% s) failed" Locale)} / / registered translator switch locale {case "en": err = enTranslations.RegisterDefaultTranslations (v, trans) case "zh": err = zhTranslations.RegisterDefaultTranslations (v) Trans) default: err = enTranslations.RegisterDefaultTranslations (v, trans)} return} return} type SignUpParam struct {Age uint8 `json: "age" binding: "gte=1,lte=130" `Name string `json: "name" binding: "required" `Email string `json: "email" binding: "required Email "`Password string `json:" password "binding:" required "`RePassword string `json:" re_password "binding:" required,eqfield=Password "`} func main () {if err: = InitTrans (" zh ") Err! = nil {fmt.Printf ("init trans failed, err:%v\ n", err) return} r: = gin.Default () r.POST ("/ signup", func (c * gin.Context) {var u SignUpParam if err: = c.ShouldBind (& u) Err! = nil {/ / get errors errs of validator.ValidationErrors type, ok: = err. (validator.ValidationErrors) if! ok {/ / non-validator.ValidationErrors type error returns c.JSON directly (http.StatusOK) Gin.H {"msg": err.Error (),}) return} / / validator.ValidationErrors type error translates c.JSON (http.StatusOK) Gin.H {"msg": errs.Translate (trans),}) return} / / saves specific business logic codes such as storage. C.JSON (http.StatusOK, "success")}) _ = r.Run (": 8999")}

Do the same thing again:

Curl-H "Content-type: application/json"-X POST-d'{"name": "q1mi", "age": 18, "email": "123.com"} 'http://127.0.0.1:8999/signup

The output this time is as follows:

{"msg": {"SignUpParam.Email": "Email must be a valid mailbox", "SignUpParam.Password": "Password is a required field", "SignUpParam.RePassword": "RePassword is a required field"} field name of custom error message

The above error prompt looks fine, but it is still almost significant. First of all, the field in the error prompt is not the field used in the request. For example, RePassword is the field name in the structure defined by our backend, while the re_password field is used in the request. How do I use a custom name for the field in the error prompt, such as the value specified by jsontag?

You just need to add a custom method to get json tag when initializing the translator as shown below.

/ / InitTrans initializes the translator func InitTrans (locale string) (err error) {/ / modify the attributes of the Validator engine in the gin framework to customize if v, ok: = binding.Validator.Engine (). (* validator.Validate) Ok {/ / registers a custom method to get json tag v.RegisterTagNameFunc (func (fld reflect.StructField) string {name: = strings.SplitN (fld.Tag.Get ("json"), "," 2) [0] if name = "-" {return ""} return name}) zhT: = zh.New () / / Chinese translator enT: = en.New () / / English translator / / the first parameter is the locale of fallback / / the following parameter is the locale that should be supported (multiple are supported) / / uni: = ut.New (zhT) ZhT) is also possible uni: = ut.New (enT, zhT, enT) / /. Liwenzhou.com...}

Try to send a request again to see the effect:

{"msg": {"SignUpParam.email": "email must be a valid mailbox", "SignUpParam.password": "password is required", "SignUpParam.re_password": "re_password is required"}}

You can see that the name of the jsontag setting in our structure is now used in the error message.

However, there is still a flaw, that is, the final error message center still has our backend defined structure name-SignUpParam, which does not need to be returned to the front end with the error prompt, and the front end does not need this value. We need to find a way to get rid of it.

Refer to the method provided by https://github.com/go-playground/validator/issues/633#issuecomment-654382345 to define a custom method to remove the prefix of the structure name:

Func removeTopStruct (fields mapping [string] string) map [string] string {res: = map [string] string {} for field, err: = range fields {resfield [strings.Index (field, ".") + 1:]] = err} return res}

We can use the above function in the code to process the translated errors:

If err: = c.ShouldBind & u) Err! = nil {/ / get errors errs of validator.ValidationErrors type, ok: = err. (validator.ValidationErrors) if! ok {/ / non-validator.ValidationErrors type error returns c.JSON directly (http.StatusOK, gin.H {"msg": err.Error () }) return} / / validator.ValidationErrors type error translates / / and uses the removeTopStruct function to remove the structure name from the field name to identify c.JSON (http.StatusOK, gin.H {"msg": removeTopStruct (errs.Translate (trans)),}) return}

Take a look at the final effect:

{"msg": {"email": "email must be a valid mailbox", "password": "password is required", "re_password": "re_password is required"}}

This time it seems to be more in line with our expected standards.

Self-defined structural body calibration method

There is still a slight problem with the above verification, that is, when it comes to some complex verification rules, such as the verification rules that the re_password field needs to be equal to the value of the password field, our custom error prompt field name method can not solve the other field names in the error message very well.

Curl-H "Content-type: application/json"-X POST-d'{"name": "q1mi", "age": 18, "email": "123.com", "password": "123"," re_password ":" 321 "} 'http://127.0.0.1:8999/signup

The final output error message is as follows:

{"msg": {"email": "email must be a valid mailbox", "re_password": "re_password must be equal to Password"}}

You can see that the structural body field name of Password still appears in the prompt in the re_password field. This is a bit of a pity, after all, the method of customizing the field name does not affect the value passed in as param.

At this point, if you want to pursue a better prompt effect, change the above Password field to the same name as json tag, you need to customize the structure verification method.

For example, we customize a verification method for SignUpParam as follows:

/ / SignUpParamStructLevelValidation Custom SignUpParam structure check function func SignUpParamStructLevelValidation (sl validator.StructLevel) {su: = sl.Current () .Interface (). (SignUpParam) if su.Password! = su.RePassword {/ / output error message The last parameter is the passed param sl.ReportError (su.RePassword, "re_password", "RePassword", "eqfield", "password")}}

Then register the custom verification method in the function that initializes the validator:

Func InitTrans (locale string) (err error) {/ / modify the attributes of the Validator engine in the gin framework to implement custom if v, ok: = binding.Validator.Engine (). (* validator.Validate); ok {/ /. Liwenzhou.com. / / register a custom check method for SignUpParam v.RegisterStructValidation (SignUpParamStructLevelValidation, SignUpParam {}) zhT: = zh.New () / / Chinese translator enT: = en.New () / / English translator / /. Liwenzhou.com...}

Finally, ask for one more time to see the effect:

{"msg": {"email": "email must be a valid mailbox", "re_password": "re_password must be equal to password"}}

This time the error message in the re_password field is as we expected.

Custom field verification method

In addition to the custom structure body verification methods described above, validator also supports custom verification methods for a field and registers with the validator instance using RegisterValidation ().

Next, let's add a field Date for SignUpParam that needs to use the custom verification method checkDate for parameter verification.

Type SignUpParam struct {Age uint8 `json: "age" binding: "gte=1,lte=130" `Name string `json: "name" binding: "required" `Email string `json: "email" binding: "required,email" `Password string `json: "password" binding: "required" `RePassword string `json: "re_password" binding: "required Eqfield=Password "`/ / Fields that need to use custom verification method checkDate for parameter verification: Date Date string `json:" date "binding:" required,datetime=2006-01-02 checkDate "`}

Where datetime=2006-01-02 is a built-in tag for verifying whether the date class parameters meet the specified format requirements. If the passed date parameter does not meet the format of 2006-01-02, the following error will be prompted:

{"msg": {"date": "date must be in the format 2006-01-02"}}

For the date field, in addition to the format requirements provided by the built-in datetime=2006-01-02, assuming that we also require that the time of the field must be a future time (later than the current time), special verification requirements for a field like this require us to use a custom field verification method.

First of all, we need to add a custom tag after the fields that need to perform a custom check. Here we use checkDate, which is separated by an English semicolon.

/ / customFunc custom field-level verification method func customFunc (fl validator.FieldLevel) bool {date, err: = time.Parse ("2006-01-02", fl.Field () .String ()) if err! = nil {return false} if date.Before (time.Now ()) {return false} return true}

Once you have defined the fields and their custom validation methods, you need to associate them and register them with our validator instance.

/ / register the custom verification method if err: = v.RegisterValidation ("checkDate", customFunc) in the verifier; err! = nil {return err}

In this way, we can verify the custom checkDate of the date field in the request parameters. Let's send the following request to test it:

Curl-H "Content-type: application/json"-X POST-d'{"name": "q1mi", "age": 18, "email": "123@qq.com", "password": "123"," re_password ":" 123", "date": "2020-01-02"} 'http://127.0.0.1:8999/signup

The response result at this time is:

{"msg": {"date": "Key: 'SignUpParam.date' Error:Field validation for' date' failed on the 'checkDate' tag"}}

This. The error message of the custom field-level verification method is very "simple and rude", which is different from the Chinese prompt style above, so we must find a way to fix it.

Custom translation method

We now need to provide a custom translation method for the custom field verification method, so as to achieve the custom display of the error message in the field.

/ / registerTranslator adds translation function func registerTranslator (tag string, msg string) validator.RegisterTranslationsFunc {return func (trans ut.Translator) error {if err: = trans.Add (tag, msg, false) for custom fields Err! = nil {return err} return nil}} / / the translation method for custom fields func translate (trans ut.Translator, fe validator.FieldError) string {msg, err: = trans.T (fe.Tag () Fe.Field () if err! = nil {panic (fe. (error). Error ())} return msg}

After defining the relevant translation method, we register our custom translation method in the InitTrans function by calling the RegisterTranslation () method.

/ / InitTrans initializes the translator func InitTrans (locale string) (err error) {/ /... liwenzhou.com... / / register translator switch locale {case "en": err = enTranslations.RegisterDefaultTranslations (v, trans) case "zh": err = zhTranslations.RegisterDefaultTranslations (v, trans) default: err = enTranslations.RegisterDefaultTranslations (v Trans)} if err! = nil {return err} / / attention! Because the trans instance / / will be used here, this step of registration should be placed after trans initialization if err: = v.RegisterTranslation ("checkDate", trans, registerTranslator ("checkDate", "{0} must be later than the current date"). Translate,) Err! = nil {return err} return} return}

Try to send the request again, and you'll get the error message you want.

{"msg": {"date": "date must be later than the current date"}} above is the content of this article on "what are the practical skills for parameter verification in golang validator library?" I believe you all have a certain understanding. I hope the content shared by the editor will be helpful to you. If you want to know more about the relevant knowledge, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report