Skip to content

Commit

Permalink
Aliased slices should be consistent with builtin slices
Browse files Browse the repository at this point in the history
In working with an API at work we had the use case on query params to accept the
following syntaxes:

- `?foo=1&foo=2&foo=3`
- `?foo=1,2,3`

Initially we were using only the former syntax, but then a new library was
developed that sent the latter syntax.  When we switched from defining our field
as `[]int` to a custom type `Ints` that implemented `UnmarshalParam` we found
that when there were multiple values for the same key, the `UnmarshalParam`
would only receive the first value and others would be lost.

This change brings
consistency between the builtin slices and the aliased slices for query
parameters.
  • Loading branch information
Brandon Hansen committed Mar 1, 2024
1 parent fa70db8 commit 04cd714
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
return errors.New("binding element must be a struct")
}

LOOP:
for i := 0; i < typ.NumField(); i++ {
typeField := typ.Field(i)
structField := val.Field(i)
Expand Down Expand Up @@ -217,11 +218,18 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
}

// Call this first, in case we're dealing with an alias to an array type
if ok, err := unmarshalField(typeField.Type.Kind(), inputValue[0], structField); ok {
if err != nil {
return err
for _, val := range inputValue {
if ok, err := unmarshalField(typeField.Type.Kind(), val, structField); ok {
if err != nil {
return err
}

// If we have one entry then we continue to the next field as to not
// overwrite the value.
if len(inputValue) == 1 {
continue LOOP
}
}
continue
}

numElems := len(inputValue)
Expand Down

0 comments on commit 04cd714

Please sign in to comment.