validator自定义验证

validator自定义验证

validator是golang的一个可扩展字段验证框架

validator简介

自定义标签验证
  • 第三方类型,需要采取自定义类型的验证

  • 有一些偏底层的内容,不方便加tag,可能各方都在调用,这时候可以采用各自的自定义验证

package validate

import (
    "database/sql"
    "database/sql/driver"
    "fmt"
    "reflect"
)

type DbBackedUser struct {
    // 第三方类型,需要采取自定义类型的验证
    Name sql.NullString `v:"required"`
    Age  sql.NullInt64  `v:"required"`
    Loc  Location       `v:"required"`
}

type Location struct {
    X float64          // 也可以加校验
    Y float64
}

// 有一些偏底层的内容,不方便加tag,可能各方都在调用,这时候可以采用自定义的验证

func CustomFieldTest() {
    validate.RegisterCustomTypeFunc(ValidateSqlValue, sql.NullInt64{}, sql.NullString{}, sql.NullFloat64{})
    validate.RegisterCustomTypeFunc(ValidateLocation)

    x := DbBackedUser{
        Name: sql.NullString{String: "kk", Valid: true},
        Age: sql.NullInt64{Int64: 20, Valid: true},  // // Valid is true if Int64 is not NULL
        Loc: Location{3.5, 1.5},
    }
    err := validate.Struct(x)
    if err != nil {
        fmt.Println(err)
    }
}


func ValidateSqlValue(field reflect.Value) interface{} {
    if valuer, ok := field.Interface().(driver.Valuer); ok {
        val ,err := valuer.Value()
        if err == nil {
            return val
        } else {
            return nil
        }
    }
    return nil
}

func ValidateLocation(field reflect.Value) interface{} {
    if valuer, ok := field.Interface().(Location); ok {
        if valuer.X != 0 && valuer.Y != 0 {
            return fmt.Sprintf("point(%v, %v)", valuer.X, valuer.Y)
        } else {
            return nil
        }
    }
    return nil
}

自定义结构体验证
  • 对结构体添加额外验证,例如业务上的验证,安全性的验证
package validate

import (
    "fmt"
    "github.com/go-playground/validator/v10"
    "reflect"
    "strings"
)

// 添加一些业务验证,补充验证


type StructLevelUser struct {
    FirstName string
    LastName  string
    Age       uint8  `v:"gte=0,lte=130"`
    Email     string `fld:"e-mail,e-mail2" v:"required,email"`         // 定义别名 e-mail
}

func StructLevel() {
    // 注册标签名,定义别的标签名
    validate.RegisterTagNameFunc(func(field reflect.StructField) string {
        name := strings.SplitN(field.Tag.Get("fld"), ",", 2)[0]
        // 返回第一个
        if name != "-" {
            return name
        }
        return ""
    })
    // 注册结构体校验
    validate.RegisterStructValidation(func(sl validator.StructLevel) {
        user := sl.Current().Interface().(StructLevelUser)
        if len(user.LastName) == 0 && len(user.FirstName) == 0 {
            sl.ReportError(user.FirstName, "fname", "FirstName", "fnamelname", "")
            sl.ReportError(user.LastName, "lname", "LastName", "fnamelname", "")
        }
    }, StructLevelUser{})

    user := &StructLevelUser{
        FirstName: "a",
        LastName:  "c",
        Age:       100,
        Email:     "ss@163.com",
    }

    err := validate.Struct(user)
    if err != nil {
        if _, ok := err.(*validator.InvalidValidationError); ok {
            fmt.Println(err)
            return
        }
        for _, err := range err.(validator.ValidationErrors) {
            fmt.Println(err)
        }
        return
    }
}
自定义标签

顾名思义,自定义一些标签去验证,使用一些除了预定义标签外的标签

package validate

import (
    "fmt"
    "github.com/go-playground/validator/v10"
)

type CustomValidateUser struct {
    Name string `v:"required,is-zhangsan"`
    Gender int `v:"gender"`         // 没有gender这个预定义tag

}

func CustomValidate() {
    validate.RegisterValidation("is-zhangsan", func(fl validator.FieldLevel) bool {
        return fl.Field().String() == "zhangsan"
    })

    validate.RegisterValidation("gender", func(fl validator.FieldLevel) bool {
        i := fl.Field().Int()
        if i != 0 && i != 1 {
            return false
        }

        return true
    })

    s := CustomValidateUser{
        Name: "zhangsan2",
        Gender: 1,
    }

    err := validate.Struct(s)
    if err != nil {
        fmt.Println(err)
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值