Skip to content

Pointer of UUID will break the Validate() function #247

@jeremy-temelpa

Description

@jeremy-temelpa

System (please complete the following information):

  • OS: macOS
  • GO Version: 1.20
  • Pkg Version: 1.5.1

Describe the bug

When the struct under validation contains a pointer of UUID, the Validate function will fail. With error msg

panic: reflect: call of reflect.Value.Len on zero Value [recovered]
	panic: reflect: call of reflect.Value.Len on zero Value

To Reproduce

// go code
type TestUser struct {
	Name             string  `validate:"required|minLen:2|maxLen:100" filter:"trim|lower"`
	Email            string  `validate:"required|email" filter:"lower"`
	OptionalString   *string `validate:"required|minLen:2|maxLen:100" filter:"trimPtr|lowerPtr"`
	TestOptionalUUID *uuid.UUID // **Problem LINE**
}

func TestValidateStruct(t *testing.T) {
	t.Parallel()
	validation.RegisterValidationFilters()
	user := TestUser{
		Name:           "  John Doe  ",
		Email:          "JOHNDOE@EXAMPLE.COM",
		OptionalString: pointer.Ref("    Optional String   "),
	}

	err := validation.ValidateStruct(&user)

	// Check if there's an error and it's as expected
	if err != nil {
		t.Errorf("Validation failed: %v", err)
	}

	// Check if the filters were applied correctly
	if user.Name != "john doe" || user.Email != "johndoe@example.com" {
		t.Errorf("Filters not applied correctly. Got Name: %s, Email: %s", user.Name, user.Email)
	}

	if pointer.Deref(user.OptionalString) != "optional string" {
		t.Errorf("Filters not applied correctly. Got OptionalString: %s", *user.OptionalString)
	}
}

func trimPointerString(val interface{}) interface{} {
	if strPtr, ok := val.(*string); ok && strPtr != nil {
		trimmed := strings.TrimSpace(*strPtr)
		return &trimmed
	}
	return val
}

func lowerPointerString(val interface{}) interface{} {
	if strPtr, ok := val.(*string); ok && strPtr != nil {
		lowered := strings.ToLower(*strPtr)
		return &lowered
	}
	return val
}

func RegisterValidationFilters() {
	validate.AddFilter("trimPtr", trimPointerString)
	validate.AddFilter("lowerPtr", lowerPointerString)
}

func ValidateStruct[T any](input *T) error {
	if input == nil {
		return nil
	}
	v := validate.Struct(input)
	if v.Validate() {
		return nil
	} else {
		return errorx.New(v.Errors.Error())
	}
}

Expected behavior

Validate() should works fine without error

Screenshots

image

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions