@@ -188,14 +188,14 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
188
188
}
189
189
structFieldKind := structField .Kind ()
190
190
inputFieldName := typeField .Tag .Get (tag )
191
- if typeField .Anonymous && structField . Kind () == reflect .Struct && inputFieldName != "" {
191
+ if typeField .Anonymous && structFieldKind == reflect .Struct && inputFieldName != "" {
192
192
// if anonymous struct with query/param/form tags, report an error
193
193
return errors .New ("query/param/form tags are not allowed with anonymous struct field" )
194
194
}
195
195
196
196
if inputFieldName == "" {
197
197
// 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
199
199
if _ , ok := structField .Addr ().Interface ().(BindUnmarshaler ); ! ok && structFieldKind == reflect .Struct {
200
200
if err := b .bindData (structField .Addr ().Interface (), data , tag ); err != nil {
201
201
return err
@@ -224,34 +224,46 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
224
224
continue
225
225
}
226
226
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
227
231
if ok , err := unmarshalInputsToField (typeField .Type .Kind (), inputValue , structField ); ok {
228
232
if err != nil {
229
233
return err
230
234
}
231
235
continue
232
236
}
233
237
234
- // Call this first, in case we're dealing with an alias to an array type
235
238
if ok , err := unmarshalInputToField (typeField .Type .Kind (), inputValue [0 ], structField ); ok {
236
239
if err != nil {
237
240
return err
238
241
}
239
242
continue
240
243
}
241
244
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 {
244
253
sliceOf := structField .Type ().Elem ().Kind ()
254
+ numElems := len (inputValue )
245
255
slice := reflect .MakeSlice (structField .Type (), numElems , numElems )
246
256
for j := 0 ; j < numElems ; j ++ {
247
257
if err := setWithProperType (sliceOf , inputValue [j ], slice .Index (j )); err != nil {
248
258
return err
249
259
}
250
260
}
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
+ }
254
264
265
+ if err := setWithProperType (structFieldKind , inputValue [0 ], structField ); err != nil {
266
+ return err
255
267
}
256
268
}
257
269
return nil
0 commit comments