validator icon indicating copy to clipboard operation
validator copied to clipboard

[Bug]: `validate: omitempty,numeric, gt=0` is checking for string len. Instead of strconv.Atoi(param.Field) > p

Open vijaykd21 opened this issue 6 months ago • 1 comments

What happened?

Hi if you use the following tag: type ABC struct { intValue string validate: omitempty, numeric, gt=0 } The validation run on this are as follows:

  1. omitempty
  2. numeric.
  3. gt=0 => this should ideally be run on the numeric equivalent of the intValue. But current implementation is checkin for the length of the Rune. Here is the code which is executed:
case reflect.String:
		p := asInt(param)

		return int64(utf8.RuneCountInString(field.String())) > p

Expected validation should be:

case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		p := asIntFromType(field.Type(), param)

		return field.Int() > p

Version

v10.26.0

Example Code

package main

import (
	"fmt"
	"github.com/go-playground/validator/v10"
)

// Port struct with validation tags
type Port struct {
	PortNum string `json:"port" validate:"omitempty,numeric,gt=0,lt=65536"`
}

func main() {
	// Initialize validator
	validate := validator.New()

	// Test a few port values
	testPorts := []string{
		"8080",   // Valid port
		"",       // Empty (valid due to omitempty)
		"0",      // Invalid - zero
		"65536",  // Invalid - too large
		"abc",    // Invalid - not numeric
	}

	fmt.Println("Port Validation Results:")
	fmt.Println("=======================")

	for _, portValue := range testPorts {
		port := Port{PortNum: portValue}
		err := validate.Struct(port)
		
		if err != nil {
			fmt.Printf("Port %q: INVALID - %v\n", portValue, err)
		} else {
			fmt.Printf("Port %q: VALID\n", portValue)
		}
	}
}

vijaykd21 avatar Jun 02 '25 16:06 vijaykd21

It's not a bug.

The validation behavior you're seeing is due to the fact that rules are applied based on the actual type defined in your struct, not the type implied by the validation tag.

Since intValue is declared as a string, the gt=0 rule applies to the length of the string - not its numeric value. Even though you've added numeric in the tag, that only checks if the string contains numeric characters; it doesn't convert the field to a numeric type for the gt rule.

One option in your case could be using the isPort validator, if that fits your use case.

Hope this helps!

nodivbyzero avatar Jun 02 '25 22:06 nodivbyzero