访问go-playground/validator中其他字段的验证标记参数

yhived7q  于 2023-06-27  发布在  Go
关注(0)|答案(1)|浏览(135)

我正在使用go-playground/validator包来验证Go中的结构。下面是我的struct定义:

GetLogRequest struct {
    CreatedAtMin      string `query:"created_at_min" validate:"omitempty,datetime=2006-01-02"`
    CreatedAtMax      string `query:"created_at_max" validate:"omitempty,datetime=2006-01-02,date_greater_than=CreatedAtMin"`
}

正如您所看到的,CreatedAtMin和CreatedAtMax字段有一个自定义日期验证,它使用datetime标记定义日期格式。我想在另一个自定义验证函数中使用相同的日期格式。下面是我的自定义验证函数的框架:

func validateDateGreaterThan(fl validator.FieldLevel) bool {
    dateMax, err := time.Parse("2006-01-02", fl.Field().String())
    if err != nil {
        return false
    }

    dateMin, err := time.Parse("2006-01-02", fl.Parent().FieldByName(fl.Param()).String())
    if err != nil {
        return false
    }

    return dateMin.After(dateMax)
}

有没有一种方法可以从我的自定义验证函数中访问另一个字段的datetime验证标记的参数,这样我就可以使用该格式,而不必将其硬编码到time.Parse函数中?
任何帮助或指导将不胜感激。谢谢你。

h5qlskok

h5qlskok1#

github.com/go-playground/validator包不导出其他验证标记的参数。因此您必须自己读取和解析标记。下面是一个演示如何做到这一点(请参阅getFormat函数)。

package main

import (
    "fmt"
    "reflect"
    "strings"
    "time"

    "github.com/go-playground/validator/v10"
)

func validateDateGreaterThan(fl validator.FieldLevel) bool {
    fallback := "2006-01-02"
    f := getFormat(fl.Parent().Type(), fl.StructFieldName(), fallback)
    dateMax, err := time.Parse(f, fl.Field().String())
    if err != nil {
        return false
    }

    minField, kind, _, found := fl.GetStructFieldOK2()
    if !found {
        panic("field not found")
    }
    if kind != reflect.String {
        panic("unsupported type")
    }
    f = getFormat(fl.Parent().Type(), fl.Param(), fallback)
    dateMin, err := time.Parse(f, minField.String())
    if err != nil {
        return false
    }

    return dateMax.After(dateMin)
}

func getFormat(typ reflect.Type, fieldName, fallback string) string {
    df, ok := typ.FieldByName(fieldName)
    if !ok {
        return fallback
    }

    tag := df.Tag.Get("validate")
    if tag == "" {
        return fallback
    }

    datetime := "datetime="
    values := strings.Split(tag, ",")
    for _, v := range values {
        if strings.HasPrefix(v, datetime) {
            return strings.TrimSpace(v[len(datetime):])
        }
    }

    return fallback
}

type GetLogRequest struct {
    CreatedAtMin string `query:"created_at_min" validate:"omitempty,datetime=2006-01-02"`
    CreatedAtMax string `query:"created_at_max" validate:"omitempty,datetime=2006-01-02,date_greater_than=CreatedAtMin"`
}

var validate *validator.Validate

func main() {
    validate = validator.New()
    if err := validate.RegisterValidation("date_greater_than", validateDateGreaterThan); err != nil {
        panic(err)
    }

    request := GetLogRequest{
        CreatedAtMin: "2023-06-07",
        CreatedAtMax: "2023-06-08",
    }

    fmt.Printf("validate error: %+v\n", validate.Struct(request))
}

相关问题