validator icon indicating copy to clipboard operation
validator copied to clipboard

uuid4 doesn't works with google uuid.UUID

Open polRk opened this issue 3 years ago • 8 comments

  • [+] I have looked at the documentation here first?
  • [+] I have looked at the examples provided that may showcase my question here?

Package version eg. v9, v10:

v10

Issue, Question or Enhancement:

Got an error: ["3dcf8eb3-4489-4777-af93-2ba289316e77"] is not valid value for uuid.UUID

Code sample, to showcase or reproduce:

type getContactRequest struct {
	ID uuid.UUID `uri:"id" binding:"required,uuid4"`
}

If i pass

type getContactRequest struct {
	ID string `uri:"id" binding:"required,uuid4"`
}
``` - It works

polRk avatar Feb 16 '22 15:02 polRk

Hey @polRk

The validator works only for string types out of the box.

But you can register a CustomTypeFunc. It would look something like this:

package main

import (
	"fmt"
	"reflect"

	"github.com/go-playground/validator/v10"
	"github.com/google/uuid"
)

type getContactRequest struct {
	ID uuid.UUID `uri:"id" validate:"required,uuid4"`
}

// use a single instance of Validate, it caches struct info
var validate *validator.Validate

func main() {

	validate = validator.New()

	// register all sql.Null* types to use the ValidateValuer CustomTypeFunc
	validate.RegisterCustomTypeFunc(ValidateUUID, uuid.UUID{})

	// build object for validation
	x := getContactRequest{ID: uuid.New()}

	err := validate.Struct(x)

	if err != nil {
		fmt.Printf("Err(s):\n%+v\n", err)
	}
}

// ValidateUUID implements validator.CustomTypeFunc
func ValidateUUID(field reflect.Value) interface{} {
	if valuer, ok := field.Interface().(uuid.UUID); ok {
		return valuer.String()
	}
	return nil
}

See more at : https://github.com/go-playground/validator/blob/master/_examples/custom/main.go and https://pkg.go.dev/github.com/go-playground/validator/v10#CustomTypeFunc and https://pkg.go.dev/github.com/go-playground/validator/v10#Validate.RegisterCustomTypeFunc

zemzale avatar Feb 16 '22 17:02 zemzale

Thank you!

polRk avatar Feb 16 '22 17:02 polRk

It doesn't work

["cb1cdadb-a93c-487b-be62-4963cef4600b"] is not valid value for uuid.UUID
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		v.RegisterCustomTypeFunc(ValidateUUID, uuid.UUID{})
		v.RegisterCustomTypeFunc(ValidateNullable, uuid.NullUUID{}, nullable.NullString{}, nullable.NullTime{})
	}
func ValidateUUID(field reflect.Value) interface{} {
	if valuer, ok := field.Interface().(uuid.UUID); ok {
		return valuer.String()
	}

	return nil
}
func ValidateNullable(field reflect.Value) interface{} {
	if valuer, ok := field.Interface().(driver.Valuer); ok {
		val, err := valuer.Value()
		if err == nil {
			return val
		}
	}

	return nil
}

polRk avatar Feb 19 '22 13:02 polRk

I think, problem with ShouldBindUri, because with ShouldBindJSON works good

polRk avatar Feb 19 '22 13:02 polRk

That error is not with this library, but https://github.com/gin-gonic/gin so you should take the issue there.

zemzale avatar Feb 19 '22 14:02 zemzale

As an aside I think that we can enhance the uuid validation to check if the type can be cast to a Stringer and if so call that function. Since most, if not all, UUID types have this function.

type Stringer interface {
    String() string
}

I'd be happy to accept a PR for that. Then no custom functions would be required.

deankarn avatar Feb 19 '22 14:02 deankarn

it works with strings only and it works like a charm!

vigo avatar Oct 24 '23 12:10 vigo

@deankarn ^ I went ahead and did my attempt at adding this in https://github.com/go-playground/validator/pull/1189

JoshGlazebrook avatar Oct 31 '23 16:10 JoshGlazebrook