英文:
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()})
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论