Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: go-playground/validator
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: go-playground/validator
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1189
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.
  • 2 commits
  • 3 files changed
  • 2 contributors

Commits on Oct 30, 2023

  1. Add support for validating against uuid values that are structs which…

    … implement the Stringer interface.
    JoshGlazebrook committed Oct 30, 2023
    Copy the full SHA
    fc09467 View commit details

Commits on Nov 4, 2023

  1. sure up new helper + add alias test

    Dean Karn committed Nov 4, 2023
    Copy the full SHA
    1ceab95 View commit details
Showing with 68 additions and 9 deletions.
  1. +9 −9 baked_in.go
  2. +17 −0 util.go
  3. +42 −0 validator_test.go
18 changes: 9 additions & 9 deletions baked_in.go
Original file line number Diff line number Diff line change
@@ -508,47 +508,47 @@ func isASCII(fl FieldLevel) bool {

// isUUID5 is the validation function for validating if the field's value is a valid v5 UUID.
func isUUID5(fl FieldLevel) bool {
return uUID5Regex.MatchString(fl.Field().String())
return fieldMatchesRegexByStringerValOrString(uUID5Regex, fl)
}

// isUUID4 is the validation function for validating if the field's value is a valid v4 UUID.
func isUUID4(fl FieldLevel) bool {
return uUID4Regex.MatchString(fl.Field().String())
return fieldMatchesRegexByStringerValOrString(uUID4Regex, fl)
}

// isUUID3 is the validation function for validating if the field's value is a valid v3 UUID.
func isUUID3(fl FieldLevel) bool {
return uUID3Regex.MatchString(fl.Field().String())
return fieldMatchesRegexByStringerValOrString(uUID3Regex, fl)
}

// isUUID is the validation function for validating if the field's value is a valid UUID of any version.
func isUUID(fl FieldLevel) bool {
return uUIDRegex.MatchString(fl.Field().String())
return fieldMatchesRegexByStringerValOrString(uUIDRegex, fl)
}

// isUUID5RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v5 UUID.
func isUUID5RFC4122(fl FieldLevel) bool {
return uUID5RFC4122Regex.MatchString(fl.Field().String())
return fieldMatchesRegexByStringerValOrString(uUID5RFC4122Regex, fl)
}

// isUUID4RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v4 UUID.
func isUUID4RFC4122(fl FieldLevel) bool {
return uUID4RFC4122Regex.MatchString(fl.Field().String())
return fieldMatchesRegexByStringerValOrString(uUID4RFC4122Regex, fl)
}

// isUUID3RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v3 UUID.
func isUUID3RFC4122(fl FieldLevel) bool {
return uUID3RFC4122Regex.MatchString(fl.Field().String())
return fieldMatchesRegexByStringerValOrString(uUID3RFC4122Regex, fl)
}

// isUUIDRFC4122 is the validation function for validating if the field's value is a valid RFC4122 UUID of any version.
func isUUIDRFC4122(fl FieldLevel) bool {
return uUIDRFC4122Regex.MatchString(fl.Field().String())
return fieldMatchesRegexByStringerValOrString(uUIDRFC4122Regex, fl)
}

// isULID is the validation function for validating if the field's value is a valid ULID.
func isULID(fl FieldLevel) bool {
return uLIDRegex.MatchString(fl.Field().String())
return fieldMatchesRegexByStringerValOrString(uLIDRegex, fl)
}

// isMD4 is the validation function for validating if the field's value is a valid MD4.
17 changes: 17 additions & 0 deletions util.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package validator

import (
"fmt"
"reflect"
"regexp"
"strconv"
"strings"
"time"
@@ -292,3 +294,18 @@ func panicIf(err error) {
panic(err.Error())
}
}

// Checks if field value matches regex. If fl.Field can be cast to Stringer, it uses the Stringer interfaces
// String() return value. Otherwise, it uses fl.Field's String() value.
func fieldMatchesRegexByStringerValOrString(regex *regexp.Regexp, fl FieldLevel) bool {
switch fl.Field().Kind() {
case reflect.String:
return regex.MatchString(fl.Field().String())
default:
if stringer, ok := fl.Field().Interface().(fmt.Stringer); ok {
return regex.MatchString(stringer.String())
} else {
return regex.MatchString(fl.Field().String())
}
}
}
42 changes: 42 additions & 0 deletions validator_test.go
Original file line number Diff line number Diff line change
@@ -4105,6 +4105,23 @@ func TestUUID3Validation(t *testing.T) {
}
}

type uuidTestType struct {
val string
}

func (u uuidTestType) String() string {
return u.val
}

type uuidAlias string

func (u uuidAlias) String() string {
return "This is a UUID " + string(u)
}

var _ fmt.Stringer = uuidTestType{}
var _ fmt.Stringer = uuidAlias("")

func TestUUIDValidation(t *testing.T) {
tests := []struct {
param string
@@ -4141,6 +4158,31 @@ func TestUUIDValidation(t *testing.T) {
}
}
}

// Test UUID validation on uuid structs type that implements Stringer interface.
structWithValidUUID := struct {
UUID uuidTestType `validate:"uuid"`
}{
UUID: uuidTestType{val: "a987fbc9-4bed-3078-cf07-9141ba07c9f3"},
}
structWithInvalidUUID := struct {
UUID uuidTestType `validate:"uuid"`
}{
UUID: uuidTestType{val: "934859"},
}

if err := validate.Struct(structWithValidUUID); err != nil {
t.Fatalf("UUID failed Error: %s", err)
}
if err := validate.Struct(structWithInvalidUUID); err == nil {
t.Fatal("UUID failed Error expected but received nil")
}

// Test on Alias type with Stringer interface.
alias := uuidAlias("a987fbc9-4bed-3078-cf07-9141ba07c9f3")
if err := validate.Var(alias, "uuid"); err != nil {
t.Fatalf("UUID failed Error: %s", err)
}
}

func TestUUID5RFC4122Validation(t *testing.T) {