gin-gonic / gin

Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.
https://gin-gonic.com/
MIT License
76.76k stars 7.92k forks source link

Binding with Omitempty and min or gte does not honour '0' case #2459

Open raybog opened 3 years ago

raybog commented 3 years ago

Description

Binding error when using omitempty along with gte or min when gte=1 or min=1 and parmaeter is 0.

How to reproduce

package main

import (
    "net/http"

    "github.com/gin-gonic/gin"
    "github.com/gin-gonic/gin/binding"
)

type Test struct {
    Test int `form:"test" binding:"omitempty,lte=10,gte=1"`
    Test2 int `form:"test2" binding:"omitempty,max=10,min=1"`
}

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

    route.GET("/test", getTest)
    route.Run(":8085")
}

func getTest(c *gin.Context) {
    var t Test
    if err := c.ShouldBindWith(&t, binding.Query); err == nil {
        c.JSON(http.StatusOK, gin.H{"message": "Test is valid!"})
    } else {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
    }
}

Expectations

$ curl "localhost:8085/test?test=0&test2=0"
{"error":"Key: 'Test.Test' Error:Field validation for 'Test' failed on the 'gte' tag\nKey: 'Test.Test2' Error:Field validation for 'Test2' failed on the 'max' tag"}

Actual result

$ curl "localhost:8085/test?test=0&test2=0"
{"message":"Test is valid!"}

Environment

unbyte commented 3 years ago

0 is treated as nil value and validators are ignored due to omiempty

PhantomX7 commented 3 years ago

you should use pointer for that, because of omitempty behavior

this is on the documentation:

Omit Empty Allows conditional validation, for example if a field is not set with a value (Determined by the "required" validator) then other validation such as min or max won't run, but if a value is set validation will run.

Required This validates that the value is not the data types default zero value. For numbers ensures value is not zero. For strings ensures value is not "". For slices, maps, pointers, interfaces, channels and functions ensures the value is not nil.

In your case, you use int where it's default value is 0, so omitempty will be triggered if it is 0.