go-playground / validatorライブラリアップデート作業メモv8 -> v10


前書き

今後同じ作業をする方と自分の振り返りのため、メモを残します。

goバージョン go-playground / validatorバージョン
v1.15.3 v10.4.1

TagName

v8のvalidatorはデフォルトのTagNameを指定してありません。
毎回validator初期化する際にTagNameを渡してます、v8の場合は以下の書き方になってます。

v8

main.go
var validate *validator.Validate
config := &validator.Config{TagName: "validate"}
validate = validator.New(config)

v9以降のTagNameのデフォルト値が validateに指定されてます、ライブラリのソースコードを見てみよう。

validator_instance.go

    v := &Validate{
        tagName:     defaultTagName,
        aliases:     make(map[string]string, len(bakedInAliases)),
        validations: make(map[string]internalValidationFuncWrapper, len(bakedInValidators)),
        tagCache:    tc,
        structCache: sc,
    }
validator_instance.go
const (
    defaultTagName        = "validate"

よって、v9以降特に指定がなければ、以下の書き方になります。

v9以降

main.go
validate = validator.New()

validator.RegisterValidation

カスタムバリデーションを作る際にvalidator.RegisterValidation()が使われます。
v8の場合以下の書方になっていました、戻り値の真偽で判断しています。

v8

main.go
...
v.RegisterValidation("bookabledate", bookableDate)
...

func bookableDate(
  v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,
  field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,
) bool {
  if date, ok := field.Interface().(time.Time); ok {
      today := time.Now()
      if date.Unix()>today.Unix(){
          return true
      }
  }
  return false
}

v9以降では、使い方は変わってないですが、検証用の関数を受けるパラメーターが簡略化されました。
fieldパラメーターなどは validator.FieldLevelに集約されました。

v9以降

main.go
...
v.RegisterValidation("bookabledate", bookableDate)
...
func bookableDate(fl validator.FieldLevel) bool {
    if  date,ok:=fl.Field().Interface().(time.Time);ok{
        today:=time.Now()
        fmt.Println("date:",date)
        if date.Unix()>today.Unix(){
            fmt.Println("date unix :",date.Unix())
            return true
        }
    }
    return false
}

validator.ValidationErrors

  • v8の validator.ValidationErrorsのタイプは map[string]*FieldError
    • FieldErrorは構造体
  • v9以降の validator.ValidationErrorsのタイプは ValidationErrors []FieldError
    • FieldErrorはインターフェース

v8では以下のような書き方でFieldErrorを生成していましたが、v9以降では使えません。

v8

main.go
validator.ValidationErrors{err: &karma.InvalidParamError{
    "xx.yy": &validator.FieldError{Field: "yy", Tag: "gt"},Err: errors.New(fmt.Sprintf(fieldErrMsg, "xx.yy", "yy", "gt")),
}

v9以降で同じエラーを生成したい場合、fieldErrorの Error()関数の書き方を真似するといいです。

errors.go
const fieldErrMsg = "Key: '%s' Error:Field validation for '%s' failed on the '%s' tag"

func (fe *fieldError) Error() string {
    return fmt.Sprintf(fieldErrMsg, fe.ns, fe.Field(), fe.tag)
}

v9以降

mian.go
const fieldErrMsg = "Key: '%s' Error:Field validation for '%s' failed on the '%s' tag"
validator.ValidationErrors{err: errors.New(fmt.Sprintf(fieldErrMsg, "xx.yy", "yy", "gt"))}