Merge pull request #361 from jservice-rvbd/unique-for-maps
Extend the unique tag to also cover map values.
Dean Karn authored 5 years ago
GitHub committed 5 years ago
0 | 0 | package validator |
1 | 1 | |
2 | 2 | import ( |
3 | "bytes" | |
3 | 4 | "context" |
5 | "crypto/sha256" | |
4 | 6 | "fmt" |
5 | 7 | "net" |
6 | 8 | "net/url" |
10 | 12 | "sync" |
11 | 13 | "time" |
12 | 14 | "unicode/utf8" |
13 | "crypto/sha256" | |
14 | "bytes" | |
15 | 15 | ) |
16 | 16 | |
17 | 17 | // Func accepts a FieldLevel interface for all validation needs. The return |
186 | 186 | return false |
187 | 187 | } |
188 | 188 | |
189 | // isUnique is the validation function for validating if each array|slice element is unique | |
189 | // isUnique is the validation function for validating if each array|slice|map value is unique | |
190 | 190 | func isUnique(fl FieldLevel) bool { |
191 | 191 | |
192 | 192 | field := fl.Field() |
194 | 194 | |
195 | 195 | switch field.Kind() { |
196 | 196 | case reflect.Slice, reflect.Array: |
197 | m := reflect.MakeMap(reflect.MapOf(fl.Field().Type().Elem(), v.Type())) | |
197 | m := reflect.MakeMap(reflect.MapOf(field.Type().Elem(), v.Type())) | |
198 | 198 | |
199 | 199 | for i := 0; i < field.Len(); i++ { |
200 | 200 | m.SetMapIndex(field.Index(i), v) |
201 | } | |
202 | return field.Len() == m.Len() | |
203 | case reflect.Map: | |
204 | m := reflect.MakeMap(reflect.MapOf(field.Type().Elem(), v.Type())) | |
205 | ||
206 | for _, k := range field.MapKeys() { | |
207 | m.SetMapIndex(field.MapIndex(k), v) | |
201 | 208 | } |
202 | 209 | return field.Len() == m.Len() |
203 | 210 | default: |
505 | 505 | Unique |
506 | 506 | |
507 | 507 | For arrays & slices, unique will ensure that there are no duplicates. |
508 | For maps, unique will ensure that there are no duplicate values. | |
508 | 509 | |
509 | 510 | Usage: unique |
510 | 511 |
7695 | 7695 | param interface{} |
7696 | 7696 | expected bool |
7697 | 7697 | }{ |
7698 | // Arrays | |
7699 | {[2]string{"a", "b"}, true}, | |
7700 | {[2]int{1, 2}, true}, | |
7701 | {[2]float64{1, 2}, true}, | |
7702 | {[2]interface{}{"a", "b"}, true}, | |
7703 | {[2]interface{}{"a", 1}, true}, | |
7704 | {[2]float64{1, 1}, false}, | |
7705 | {[2]int{1, 1}, false}, | |
7706 | {[2]string{"a", "a"}, false}, | |
7707 | {[2]interface{}{"a", "a"}, false}, | |
7708 | {[4]interface{}{"a", 1, "b", 1}, false}, | |
7709 | // Slices | |
7698 | 7710 | {[]string{"a", "b"}, true}, |
7699 | 7711 | {[]int{1, 2}, true}, |
7700 | 7712 | {[]float64{1, 2}, true}, |
7705 | 7717 | {[]string{"a", "a"}, false}, |
7706 | 7718 | {[]interface{}{"a", "a"}, false}, |
7707 | 7719 | {[]interface{}{"a", 1, "b", 1}, false}, |
7720 | // Maps | |
7721 | {map[string]string{"one": "a", "two": "b"}, true}, | |
7722 | {map[string]int{"one": 1, "two": 2}, true}, | |
7723 | {map[string]float64{"one": 1, "two": 2}, true}, | |
7724 | {map[string]interface{}{"one": "a", "two": "b"}, true}, | |
7725 | {map[string]interface{}{"one": "a", "two": 1}, true}, | |
7726 | {map[string]float64{"one": 1, "two": 1}, false}, | |
7727 | {map[string]int{"one": 1, "two": 1}, false}, | |
7728 | {map[string]string{"one": "a", "two": "a"}, false}, | |
7729 | {map[string]interface{}{"one": "a", "two": "a"}, false}, | |
7730 | {map[string]interface{}{"one": "a", "two": 1, "three": "b", "four": 1}, false}, | |
7708 | 7731 | } |
7709 | 7732 | |
7710 | 7733 | validate := New() |