LoginSignup
28
22

More than 5 years have passed since last update.

【Golang】echoとvalidator.v9を使ったカスタムバリデーションのサンプル

Posted at

Golangのechovalidator.v9を使って、独自のバリデータタグを定義できるまでの手順の紹介.

echoでカスタムバリデータを扱う

公式ページを参考にしつつ、echo.Validatorにカスタムバリデータを設定する.  
まずはカスタムバリデータを作成する.

// CustomValidator
type CustomValidator struct {
    validator *validator.Validate
}

// NewValidator
func NewValidator() echo.Validator {
    return &CustomValidator{validator: validator.New()}
}

// Validate validate
func (cv *CustomValidator) Validate(i interface{}) error {
    return cv.validator.Struct(i)
}

作成したバリデータをe.Validatorに設定.

main.go
func main() {
    e := echo.New()
    e.Validator = NewValidator()
    e.GET("/", func(c echo.Context) (err error) {
        u := new(User)
        if err = c.Bind(u); err != nil {
            return
        }
        if err = c.Validate(u); err != nil {
            return
        }
        return c.JSON(http.StatusOK, u)
    })
    e.Logger.Fatal(e.Start(":1323"))
}

これでvalidator.v9が使えるようになった.

バリデーションを実施する

validator.v9でバリデーションを実施してみる.
例えばFooStructを定義して、validate項目にrequiedタグを設定すると必須になる.
他にも色々なタグがあって便利なので、公式ページをみて自分の用途にあったバリデーションを設定して使う.

// Foo struct
type Foo struct {
    Bar string `query:"bar" validate:"requied"`
}

func main() {
    e := echo.New()
    e.Validator = NewValidator()
    e.GET("/", func(c echo.Context) (err error) {
        u := new(Foo)
        if err = c.Bind(u); err != nil {
            rreturn echo.NewHTTPError(http.StatusBadRequest, err.Error())
        }
        if err = c.Validate(u); err != nil {
            return echo.NewHTTPError(http.StatusBadRequest, err.(validator.ValidationErrors).Error())
        }
        return c.JSON(http.StatusOK, u)
    })
    e.Logger.Fatal(e.Start(":1323"))
}

これでrequiedバリデーションが設定され,クエリパラメータにbar項目を含めないとバリデーションに失敗するようになった.

$ curl -X GET "http://127.0.0.1:1322"
{"message":"Key: 'Foo.Bar' Error:Field validation for 'Bar' failed on the 'required' tag"}

$ curl -X GET "http://127.0.0.1:1322/?bar=hoge"
{"Bar":"hoge"}

独自のカスタムバリデーションを定義する

独自のバリデーションタグを作成したい場合は、 validator.RegisterValidation()を利用する.
validator.RegisterValidation()を設定するためにまずはboolを返すメソッドを定義する.
以下は文字列がhogehogeと一致しない場合に失敗するバリデーションの例.ここで好きに条件を定義できる.

// CustomValidate
func CustomValidate(fl validator.FieldLevel) bool {
    return fl.Field().String() == "hogehoge"
}

バリデーションが作成できたのでカスタムバリデータにCustomValidate()を追加する.

// CustomValidator
type CustomValidator struct {
    validator *validator.Validate
}

// NewValidator
func NewValidator() echo.Validator {
    return &CustomValidator{validator: validator.New()}
}

// Validate validate
func (cv *CustomValidator) Validate(i interface{}) error {
    cv.validator.RegisterValidation("hogehoge", CustomValidate)
    return cv.validator.Struct(i)
}

これで新たにhogehogeバリデーションタグを作ることができた.
先ほど定義したFoo Structにルールを追加する.

// Foo struct
type Foo struct {
    Bar string `query:"bar" validate:"requied,hogehoge"`
}

これでhogehogeルールが追加され、独自タグでのバリデーションが行えるようになった.
今までのrequiredも動作している.

$ curl -X GET "http://127.0.0.1:1322/?bar=hoge"
{"message":"Key: 'Foo.Bar' Error:Field validation for 'Bar' failed on the 'hogehoge' tag"}

$ curl -X GET "http://127.0.0.1:1322"
{"message":"Key: 'Foo.Bar' Error:Field validation for 'Bar' failed on the 'required' tag"}

$ curl -X GET "http://127.0.0.1:1322/?bar=hogehoge"
{"Bar":"hogehoge"}

こんな感じでechoとvalidator.v9を利用して、簡単にバリデーションが実施できる.
validator.v9はデフォルト状態でも簡単なアプリには必要十分なバリデーションが揃っているし、紹介した以外にも色々設定できることもあるようなのでどんどん使っていきたい.

全体コード

最終的なコードはこんな感じでした.

main.go
package main

import (
    "net/http"

    "github.com/labstack/echo"
    "gopkg.in/go-playground/validator.v9"
)

// CustomValidator
type CustomValidator struct {
    validator *validator.Validate
}

// NewValidator
func NewValidator() echo.Validator {
    return &CustomValidator{validator: validator.New()}
}

// Validate validate
func (cv *CustomValidator) Validate(i interface{}) error {
    cv.validator.RegisterValidation("hogehoge", CustomValidate)
    return cv.validator.Struct(i)
}

// CustomValidate
func CustomValidate(fl validator.FieldLevel) bool {
    return fl.Field().String() == "hogehoge"
}

// Foo struct
type Foo struct {
    Bar string `query:"bar" validate:"required,hogehoge"`
}

func main() {
    e := echo.New()
    e.Validator = NewValidator()
    e.GET("/", func(c echo.Context) (err error) {
        u := new(Foo)
        if err = c.Bind(u); err != nil {
            return echo.NewHTTPError(http.StatusBadRequest, err.Error())
        }
        if err = c.Validate(u); err != nil {
            return echo.NewHTTPError(http.StatusBadRequest, err.(validator.ValidationErrors).Error())
        }
        return c.JSON(http.StatusOK, u)
    })
    e.Logger.Fatal(e.Start(":1322"))
}
28
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
22