@@ -188,14 +188,14 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
188188 }
189189 structFieldKind := structField .Kind ()
190190 inputFieldName := typeField .Tag .Get (tag )
191- if typeField .Anonymous && structField . Kind () == reflect .Struct && inputFieldName != "" {
191+ if typeField .Anonymous && structFieldKind == reflect .Struct && inputFieldName != "" {
192192 // if anonymous struct with query/param/form tags, report an error
193193 return errors .New ("query/param/form tags are not allowed with anonymous struct field" )
194194 }
195195
196196 if inputFieldName == "" {
197197 // If tag is nil, we inspect if the field is a not BindUnmarshaler struct and try to bind data into it (might contains fields with tags).
198- // structs that implement BindUnmarshaler are binded only when they have explicit tag
198+ // structs that implement BindUnmarshaler are bound only when they have explicit tag
199199 if _ , ok := structField .Addr ().Interface ().(BindUnmarshaler ); ! ok && structFieldKind == reflect .Struct {
200200 if err := b .bindData (structField .Addr ().Interface (), data , tag ); err != nil {
201201 return err
@@ -224,34 +224,46 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
224224 continue
225225 }
226226
227+ // NOTE: algorithm here is not particularly sophisticated. It probably does not work with absurd types like `**[]*int`
228+ // but it is smart enough to handle niche cases like `*int`,`*[]string`,`[]*int` .
229+
230+ // try unmarshalling first, in case we're dealing with an alias to an array type
227231 if ok , err := unmarshalInputsToField (typeField .Type .Kind (), inputValue , structField ); ok {
228232 if err != nil {
229233 return err
230234 }
231235 continue
232236 }
233237
234- // Call this first, in case we're dealing with an alias to an array type
235238 if ok , err := unmarshalInputToField (typeField .Type .Kind (), inputValue [0 ], structField ); ok {
236239 if err != nil {
237240 return err
238241 }
239242 continue
240243 }
241244
242- numElems := len (inputValue )
243- if structFieldKind == reflect .Slice && numElems > 0 {
245+ // we could be dealing with pointer to slice `*[]string` so dereference it. There are wierd OpenAPI generators
246+ // that could create struct fields like that.
247+ if structFieldKind == reflect .Pointer {
248+ structFieldKind = structField .Elem ().Kind ()
249+ structField = structField .Elem ()
250+ }
251+
252+ if structFieldKind == reflect .Slice {
244253 sliceOf := structField .Type ().Elem ().Kind ()
254+ numElems := len (inputValue )
245255 slice := reflect .MakeSlice (structField .Type (), numElems , numElems )
246256 for j := 0 ; j < numElems ; j ++ {
247257 if err := setWithProperType (sliceOf , inputValue [j ], slice .Index (j )); err != nil {
248258 return err
249259 }
250260 }
251- val . Field ( i ) .Set (slice )
252- } else if err := setWithProperType ( typeField . Type . Kind (), inputValue [ 0 ], structField ); err != nil {
253- return err
261+ structField .Set (slice )
262+ continue
263+ }
254264
265+ if err := setWithProperType (structFieldKind , inputValue [0 ], structField ); err != nil {
266+ return err
255267 }
256268 }
257269 return nil
0 commit comments