Merge pull request #361 from jservice-rvbd/unique-for-maps

Extend the unique tag to also cover map values.
pull/362/head
Dean Karn 6 years ago committed by GitHub
commit b297167b88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      baked_in.go
  2. 1
      doc.go
  3. 23
      validator_test.go

@ -1,7 +1,9 @@
package validator
import (
"bytes"
"context"
"crypto/sha256"
"fmt"
"net"
"net/url"
@ -11,8 +13,6 @@ import (
"sync"
"time"
"unicode/utf8"
"crypto/sha256"
"bytes"
)
// Func accepts a FieldLevel interface for all validation needs. The return
@ -187,7 +187,7 @@ func isOneOf(fl FieldLevel) bool {
return false
}
// isUnique is the validation function for validating if each array|slice element is unique
// isUnique is the validation function for validating if each array|slice|map value is unique
func isUnique(fl FieldLevel) bool {
field := fl.Field()
@ -195,12 +195,19 @@ func isUnique(fl FieldLevel) bool {
switch field.Kind() {
case reflect.Slice, reflect.Array:
m := reflect.MakeMap(reflect.MapOf(fl.Field().Type().Elem(), v.Type()))
m := reflect.MakeMap(reflect.MapOf(field.Type().Elem(), v.Type()))
for i := 0; i < field.Len(); i++ {
m.SetMapIndex(field.Index(i), v)
}
return field.Len() == m.Len()
case reflect.Map:
m := reflect.MakeMap(reflect.MapOf(field.Type().Elem(), v.Type()))
for _, k := range field.MapKeys() {
m.SetMapIndex(field.MapIndex(k), v)
}
return field.Len() == m.Len()
default:
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
}

@ -506,6 +506,7 @@ to the top level struct.
Unique
For arrays & slices, unique will ensure that there are no duplicates.
For maps, unique will ensure that there are no duplicate values.
Usage: unique

@ -7696,6 +7696,18 @@ func TestUniqueValidation(t *testing.T) {
param interface{}
expected bool
}{
// Arrays
{[2]string{"a", "b"}, true},
{[2]int{1, 2}, true},
{[2]float64{1, 2}, true},
{[2]interface{}{"a", "b"}, true},
{[2]interface{}{"a", 1}, true},
{[2]float64{1, 1}, false},
{[2]int{1, 1}, false},
{[2]string{"a", "a"}, false},
{[2]interface{}{"a", "a"}, false},
{[4]interface{}{"a", 1, "b", 1}, false},
// Slices
{[]string{"a", "b"}, true},
{[]int{1, 2}, true},
{[]float64{1, 2}, true},
@ -7706,6 +7718,17 @@ func TestUniqueValidation(t *testing.T) {
{[]string{"a", "a"}, false},
{[]interface{}{"a", "a"}, false},
{[]interface{}{"a", 1, "b", 1}, false},
// Maps
{map[string]string{"one": "a", "two": "b"}, true},
{map[string]int{"one": 1, "two": 2}, true},
{map[string]float64{"one": 1, "two": 2}, true},
{map[string]interface{}{"one": "a", "two": "b"}, true},
{map[string]interface{}{"one": "a", "two": 1}, true},
{map[string]float64{"one": 1, "two": 1}, false},
{map[string]int{"one": 1, "two": 1}, false},
{map[string]string{"one": "a", "two": "a"}, false},
{map[string]interface{}{"one": "a", "two": "a"}, false},
{map[string]interface{}{"one": "a", "two": 1, "three": "b", "four": 1}, false},
}
validate := New()

Loading…
Cancel
Save