Search code examples
govalidationsnakecasing

How to compose snake case binding tag with go-playground/validator?


As title, since I'm a newbie to golang, I'm a little bit confused of the binding tag for some custom format.

For example, there's a struct with a few of fields like this

type user struct {
   name  `json:"name" binding:"required"`
   hobby `json:"name" binding:"required"`
}

and the name field is supposed to support lowercase and underscore only (e.g. john_cage, david) but after I read the document of validator, still have no idea about that. validator github Is there's any good suggestion or solution for my case? Thanks in advance.

Read the document, google similar questions, try to compose the customer binding tag, etc.


Solution

  • binding tag is from gin, correct struct tag for validator is validate. Since there is no vaildation for snake_case, you should make your own. And don't forget to export the fields(Hobby, Name). If you not, (ex: hobby, name) validator will ignore the fields.

    package main
    
    import (
        "fmt"
        "strings"
    
        "github.com/go-playground/validator/v10"
    )
    
    type user struct {
        Hobby string `json:"name" validate:"required,snakecase"`
    }
    
    func main() {
        v := validator.New()
        _ = v.RegisterValidation("snakecase", validateSnakeCase)
    
        correct := user{"playing_game"}
        Incorrect := user{"playingGame"}
    
        err := v.Struct(correct)
        fmt.Println(err) // nil
    
        err = v.Struct(Incorrect)
        fmt.Println(err) // error
    }
    
    const allows = "abcdefghijklmnopqrstuvwxyz_"
    
    func validateSnakeCase(fl validator.FieldLevel) bool {
        str := fl.Field().String()
        for i := range str {
            if !strings.Contains(allows, str[i:i+1]) {
                return false
            }
        }
    
        return true
    }
    
    

    Playground

    If you want to register the function via gin, check this out