自定义验证器以比较两个字段

huangapple go评论70阅读模式
英文:

Custom validator to compare two fields

问题

我有两个字段 - StartTime 和 EndTime - 它们都是 time.Time 类型,并且它们都在同一个结构体中。如何创建一个自定义验证器来确保 EndTime 在 StartTime 的 24 小时内?我在设置 validator.Func 时遇到了困难,无法获取两个字段的值以进行比较(我知道如何比较)。

var validEndTime validator.Func = func(fl validator.FieldLevel) bool {
    endTime, ok := fl.F().Interface().(time.Time)

    if ok {
        startTime := fl.Parent().Elem().FieldByName("StartTime").Interface().(time.Time)
        duration := endTime.Sub(startTime)
        if duration.Hours() > 24 {
            return false
        }
    }
    return true
}

这是我开始编写的示例函数。我在其中使用了 fl.Parent().Elem().FieldByName("StartTime") 来获取 StartTime 字段的值,并使用 endTime.Sub(startTime) 来计算两个时间之间的持续时间。然后,我检查持续时间是否超过了 24 小时,并返回相应的验证结果。希望对你有帮助!

英文:

I have two fields - StartTime and EndTime - which are both of the type time.Time and they are both within the same struct. How would one go about create a custom validator to ensure that EndTime is within 24 hours of StartTime? I am having trouble setting up the validator.Func to get both field values so that I may compare them (which I know how to do).

var validEndTime validator.Func = func(fl validator.FieldLevel) bool {
    endTime, ok := fl.F().Interface().(time.Time)

	if ok {
		today := time.Now()
		if today.After(date) {
			return false
		}
	}
	return true
}

This is the example function I have started to write.

答案1

得分: 1

你可以使用fl.Parent()来获取结构体。

package main
import (
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/go-playground/validator/v10"
)

// Booking包含绑定和验证的数据。
type Booking struct {
	CheckIn  time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"`
	CheckOut time.Time `form:"check_out" binding:"required" time_format:"2006-01-02"`
}

var bookableDate validator.Func = func(fl validator.FieldLevel) bool {
	date, ok := fl.Field().Interface().(time.Time)
	if ok {
		booking, ok2 := fl.Parent().Interface().(*Booking)
		if ok2 && booking.CheckOut.Unix()-date.Unix() > 24*3600 {
			return false
		}
	}
	return true
}

func main() {
	route := gin.Default()

	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		v.RegisterValidation("bookabledate", bookableDate)
	}

	route.GET("/bookable", getBookable)
	route.Run(":8085")
}

func getBookable(c *gin.Context) {
	var b Booking
	if err := c.ShouldBindWith(&b, binding.Query); err == nil {
		c.JSON(http.StatusOK, gin.H{"message": "Booking dates are valid!"})
	} else {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
	}
}
英文:

you can use fl.Parent() to get the struct

package main
import (
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/go-playground/validator/v10"
)

// Booking contains binded and validated data.
type Booking struct {
	CheckIn  time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"`
	CheckOut time.Time `form:"check_out" binding:"required" time_format:"2006-01-02"`
}

var bookableDate validator.Func = func(fl validator.FieldLevel) bool {
	date, ok := fl.Field().Interface().(time.Time)
	if ok {
		booking, ok2 := fl.Parent().Interface().(*Booking)
		if ok2 && booking.CheckOut.Unix() - date.Unix() > 24*3600 {
			return false
		}
	}
	return true
}

func main() {
	route := gin.Default()

	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		v.RegisterValidation("bookabledate", bookableDate)
	}

	route.GET("/bookable", getBookable)
	route.Run(":8085")
}

func getBookable(c *gin.Context) {
	var b Booking
	if err := c.ShouldBindWith(&b, binding.Query); err == nil {
		c.JSON(http.StatusOK, gin.H{"message": "Booking dates are valid!"})
	} else {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
	}
}

huangapple
  • 本文由 发表于 2021年8月16日 09:11:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/68796484.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定