绑定验证

未匹配的标注

Iris本身并没有提供内置的模型验证器,使用第三方包 go-playground/validator.v9 用作验证。更全面的验证标签查询,请参阅这儿。代码示例请访问详情代码

你需要配置的标签必须与想设置的所有结构体字段保持一致。例如当你使用 JSON 来绑定,你设置的json就应该是这样 json:"fieldname".

绑定验证

模型结构体标签本质是只是一个标志占位,本身意义不大。它的主要作用在于,将字段与验证规则作了显性映射。Golang可通过反射来获取动态变量类型及其值,从而间接使用验证包内对应的验证方法。

package main

import (
    "fmt"

    "github.com/kataras/iris"
    "gopkg.in/go-playground/validator.v9"
)

// User 包含用户信息.
type User struct {
    FirstName      string     `json:"fname"`
    LastName       string     `json:"lname"`
    Age            uint8      `json:"age" validate:"gte=0,lte=130"`
    Email          string     `json:"email" validate:"required,email"`
    FavouriteColor string     `json:"favColor" validate:"hexcolor|rgb|rgba"`
    Addresses      []*Address `json:"addresses" validate:"required,dive,required"`
}

// 包含单个用户的地址信息
type Address struct {
    Street string `json:"street" validate:"required"`
    City   string `json:"city" validate:"required"`
    Planet string `json:"planet" validate:"required"`
    Phone  string `json:"phone" validate:"required"`
}

// 使用 Validate单例, 缓存结构体信息
var validate *validator.Validate

func main() {
    validate = validator.New()

    // 注册 'User' 验证
    // 注意: 一定注册非指针 'User' 类型, 在对它的类型检查时,验证器内部会引用。
    validate.RegisterStructValidation(UserStructLevelValidation, User{})

    app := iris.New()
    app.Post("/user", func(ctx iris.Context) {
        var user User
        if err := ctx.ReadJSON(&user); err != nil {
            // 错误句柄
        }

        // 对于无效的输入返回 InvalidValidationError 类型错误
        // nil 或 ValidationErrors ( []FieldError )
        err := validate.Struct(user)
        if err != nil {

           // 只有当您的代码可能生成一个无效的验证值时,才需要进行此检查,
           // 例如接口的值为nil,大多数情况下(包括我自己)都没有这样的代码。
            if _, ok := err.(*validator.InvalidValidationError); ok {
                ctx.StatusCode(iris.StatusInternalServerError)
                ctx.WriteString(err.Error())
                return
            }

            ctx.StatusCode(iris.StatusBadRequest)
            for _, err := range err.(validator.ValidationErrors) {
                fmt.Println()
                fmt.Println(err.Namespace())
                fmt.Println(err.Field())
                fmt.Println(err.StructNamespace())
                fmt.Println(err.StructField())
                fmt.Println(err.Tag())
                fmt.Println(err.ActualTag())
                fmt.Println(err.Kind())
                fmt.Println(err.Type())
                fmt.Println(err.Value())
                fmt.Println(err.Param())
                fmt.Println()
            }

            return
        }

        // 数据持久化,存入数据库..
    })

    app.Run(iris.Addr(":8080"))
}

func UserStructLevelValidation(sl validator.StructLevel) {
    user := sl.Current().Interface().(User)

    if len(user.FirstName) == 0 && len(user.LastName) == 0 {
        sl.ReportError(user.FirstName, "FirstName", "fname", "fnameorlname", "")
        sl.ReportError(user.LastName, "LastName", "lname", "fnameorlname", "")
    }
}

测试效果

{
    "fname": "",
    "lname": "",
    "age": 45,
    "email": "mail@example.com",
    "favColor": "#000",
    "addresses": [{
        "street": "Eavesdown Docks",
        "planet": "Persphone",
        "phone": "none",
        "city": "Unknown"
    }]
}

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
pardon110
讨论数量: 0
发起讨论 只看当前版本


暂无话题~