Skip to content

Commit d04a036

Browse files
committed
Implement unique=FieldName
1 parent 556b9da commit d04a036

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
@@ -224,14 +224,28 @@ func isOneOf(fl FieldLevel) bool {
224224
func isUnique(fl FieldLevel) bool {
225225

226226
field := fl.Field()
227+
param := fl.Param()
227228
v := reflect.ValueOf(struct{}{})
228229

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

246+
m := reflect.MakeMap(reflect.MapOf(sf.Type, v.Type()))
233247
for i := 0; i < field.Len(); i++ {
234-
m.SetMapIndex(field.Index(i), v)
248+
m.SetMapIndex(field.Index(i).FieldByName(param), v)
235249
}
236250
return field.Len() == m.Len()
237251
case reflect.Map:

validator_test.go

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

8163+
func TestUniqueValidationStructSlice(t *testing.T) {
8164+
testStructs := []struct {
8165+
A string
8166+
B string
8167+
}{
8168+
{A: "one", B: "two"},
8169+
{A: "one", B: "three"},
8170+
}
8171+
8172+
tests := []struct {
8173+
target interface{}
8174+
param string
8175+
expected bool
8176+
}{
8177+
{testStructs, "unique", true},
8178+
{testStructs, "unique=A", false},
8179+
{testStructs, "unique=B", true},
8180+
}
8181+
8182+
validate := New()
8183+
8184+
for i, test := range tests {
8185+
8186+
errs := validate.Var(test.target, test.param)
8187+
8188+
if test.expected {
8189+
if !IsEqual(errs, nil) {
8190+
t.Fatalf("Index: %d unique failed Error: %v", i, errs)
8191+
}
8192+
} else {
8193+
if IsEqual(errs, nil) {
8194+
t.Fatalf("Index: %d unique failed Error: %v", i, errs)
8195+
} else {
8196+
val := getError(errs, "", "")
8197+
if val.Tag() != "unique" {
8198+
t.Fatalf("Index: %d unique failed Error: %v", i, errs)
8199+
}
8200+
}
8201+
}
8202+
}
8203+
PanicMatches(t, func() { validate.Var(testStructs, "unique=C") }, "Bad field name C")
8204+
}
8205+
81638206
func TestHTMLValidation(t *testing.T) {
81648207
tests := []struct {
81658208
param string

0 commit comments

Comments
 (0)