@@ -30,6 +30,13 @@ type BindUnmarshaler interface {
3030 UnmarshalParam (param string ) error
3131}
3232
33+ // bindMultipleUnmarshaler is used by binder to unmarshal multiple values from request at once to
34+ // type implementing this interface. For example request could have multiple query fields `?a=1&a=2&b=test` in that case
35+ // for `a` following slice `["1", "2"] will be passed to unmarshaller.
36+ type bindMultipleUnmarshaler interface {
37+ UnmarshalParams (params []string ) error
38+ }
39+
3340// BindPathParams binds path params to bindable object
3441func (b * DefaultBinder ) BindPathParams (c Context , i interface {}) error {
3542 names := c .ParamNames ()
@@ -217,8 +224,15 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
217224 continue
218225 }
219226
227+ if ok , err := unmarshalInputsToField (typeField .Type .Kind (), inputValue , structField ); ok {
228+ if err != nil {
229+ return err
230+ }
231+ continue
232+ }
233+
220234 // Call this first, in case we're dealing with an alias to an array type
221- if ok , err := unmarshalField (typeField .Type .Kind (), inputValue [0 ], structField ); ok {
235+ if ok , err := unmarshalInputToField (typeField .Type .Kind (), inputValue [0 ], structField ); ok {
222236 if err != nil {
223237 return err
224238 }
@@ -245,7 +259,7 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
245259
246260func setWithProperType (valueKind reflect.Kind , val string , structField reflect.Value ) error {
247261 // But also call it here, in case we're dealing with an array of BindUnmarshalers
248- if ok , err := unmarshalField (valueKind , val , structField ); ok {
262+ if ok , err := unmarshalInputToField (valueKind , val , structField ); ok {
249263 return err
250264 }
251265
@@ -286,33 +300,39 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V
286300 return nil
287301}
288302
289- func unmarshalField (valueKind reflect.Kind , val string , field reflect.Value ) (bool , error ) {
290- switch valueKind {
291- case reflect . Ptr :
292- return unmarshalFieldPtr ( val , field )
293- default :
294- return unmarshalFieldNonPtr ( val , field )
303+ func unmarshalInputsToField (valueKind reflect.Kind , values [] string , field reflect.Value ) (bool , error ) {
304+ if valueKind == reflect . Ptr {
305+ if field . IsNil () {
306+ field . Set ( reflect . New ( field . Type (). Elem ()) )
307+ }
308+ field = field . Elem ( )
295309 }
296- }
297310
298- func unmarshalFieldNonPtr (value string , field reflect.Value ) (bool , error ) {
299311 fieldIValue := field .Addr ().Interface ()
300- if unmarshaler , ok := fieldIValue .(BindUnmarshaler ); ok {
301- return true , unmarshaler .UnmarshalParam (value )
302- }
303- if unmarshaler , ok := fieldIValue .(encoding.TextUnmarshaler ); ok {
304- return true , unmarshaler .UnmarshalText ([]byte (value ))
312+ unmarshaler , ok := fieldIValue .(bindMultipleUnmarshaler )
313+ if ! ok {
314+ return false , nil
305315 }
306-
307- return false , nil
316+ return true , unmarshaler .UnmarshalParams (values )
308317}
309318
310- func unmarshalFieldPtr (value string , field reflect.Value ) (bool , error ) {
311- if field .IsNil () {
312- // Initialize the pointer to a nil value
313- field .Set (reflect .New (field .Type ().Elem ()))
319+ func unmarshalInputToField (valueKind reflect.Kind , val string , field reflect.Value ) (bool , error ) {
320+ if valueKind == reflect .Ptr {
321+ if field .IsNil () {
322+ field .Set (reflect .New (field .Type ().Elem ()))
323+ }
324+ field = field .Elem ()
314325 }
315- return unmarshalFieldNonPtr (value , field .Elem ())
326+
327+ fieldIValue := field .Addr ().Interface ()
328+ switch unmarshaler := fieldIValue .(type ) {
329+ case BindUnmarshaler :
330+ return true , unmarshaler .UnmarshalParam (val )
331+ case encoding.TextUnmarshaler :
332+ return true , unmarshaler .UnmarshalText ([]byte (val ))
333+ }
334+
335+ return false , nil
316336}
317337
318338func setIntField (value string , bitSize int , field reflect.Value ) error {
0 commit comments