Skip to content

Commit 8f60426

Browse files
shihanngDean Karn
authored andcommitted
Implement unique=FieldName
1 parent 1effcb0 commit 8f60426

File tree

2 files changed

+59
-2
lines changed

2 files changed

+59
-2
lines changed

baked_in.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,14 +228,28 @@ func isOneOf(fl FieldLevel) bool {
228228
func isUnique(fl FieldLevel) bool {
229229

230230
field := fl.Field()
231+
param := fl.Param()
231232
v := reflect.ValueOf(struct{}{})
232233

233234
switch field.Kind() {
234235
case reflect.Slice, reflect.Array:
235-
m := reflect.MakeMap(reflect.MapOf(field.Type().Elem(), v.Type()))
236+
if param == "" {
237+
m := reflect.MakeMap(reflect.MapOf(field.Type().Elem(), v.Type()))
238+
239+
for i := 0; i < field.Len(); i++ {
240+
m.SetMapIndex(field.Index(i), v)
241+
}
242+
return field.Len() == m.Len()
243+
}
244+
245+
sf, ok := field.Type().Elem().FieldByName(param)
246+
if !ok {
247+
panic(fmt.Sprintf("Bad field name %s", param))
248+
}
236249

250+
m := reflect.MakeMap(reflect.MapOf(sf.Type, v.Type()))
237251
for i := 0; i < field.Len(); i++ {
238-
m.SetMapIndex(field.Index(i), v)
252+
m.SetMapIndex(field.Index(i).FieldByName(param), v)
239253
}
240254
return field.Len() == m.Len()
241255
case reflect.Map:

validator_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8185,6 +8185,49 @@ func TestUniqueValidation(t *testing.T) {
81858185
PanicMatches(t, func() { _ = validate.Var(1.0, "unique") }, "Bad field type float64")
81868186
}
81878187

8188+
func TestUniqueValidationStructSlice(t *testing.T) {
8189+
testStructs := []struct {
8190+
A string
8191+
B string
8192+
}{
8193+
{A: "one", B: "two"},
8194+
{A: "one", B: "three"},
8195+
}
8196+
8197+
tests := []struct {
8198+
target interface{}
8199+
param string
8200+
expected bool
8201+
}{
8202+
{testStructs, "unique", true},
8203+
{testStructs, "unique=A", false},
8204+
{testStructs, "unique=B", true},
8205+
}
8206+
8207+
validate := New()
8208+
8209+
for i, test := range tests {
8210+
8211+
errs := validate.Var(test.target, test.param)
8212+
8213+
if test.expected {
8214+
if !IsEqual(errs, nil) {
8215+
t.Fatalf("Index: %d unique failed Error: %v", i, errs)
8216+
}
8217+
} else {
8218+
if IsEqual(errs, nil) {
8219+
t.Fatalf("Index: %d unique failed Error: %v", i, errs)
8220+
} else {
8221+
val := getError(errs, "", "")
8222+
if val.Tag() != "unique" {
8223+
t.Fatalf("Index: %d unique failed Error: %v", i, errs)
8224+
}
8225+
}
8226+
}
8227+
}
8228+
PanicMatches(t, func() { validate.Var(testStructs, "unique=C") }, "Bad field name C")
8229+
}
8230+
81888231
func TestHTMLValidation(t *testing.T) {
81898232
tests := []struct {
81908233
param string

0 commit comments

Comments
 (0)