diff --git a/pkg/conversion/queryparams/convert.go b/pkg/conversion/queryparams/convert.go index a9ef5b9796a..ffa50170de0 100644 --- a/pkg/conversion/queryparams/convert.go +++ b/pkg/conversion/queryparams/convert.go @@ -50,6 +50,10 @@ func formatValue(value interface{}) string { return fmt.Sprintf("%v", value) } +func isPointerKind(kind reflect.Kind) bool { + return kind == reflect.Ptr +} + func isValueKind(kind reflect.Kind) bool { switch kind { case reflect.String, reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, @@ -92,11 +96,11 @@ func Convert(obj runtime.Object) (url.Values, error) { case reflect.Ptr, reflect.Interface: sv = reflect.ValueOf(obj).Elem() default: - return nil, fmt.Errorf("Expecting a pointer or interface") + return nil, fmt.Errorf("expecting a pointer or interface") } st := sv.Type() if st.Kind() != reflect.Struct { - return nil, fmt.Errorf("Expecting a pointer to a struct") + return nil, fmt.Errorf("expecting a pointer to a struct") } for i := 0; i < st.NumField(); i++ { field := sv.Field(i) @@ -105,10 +109,18 @@ func Convert(obj runtime.Object) (url.Values, error) { continue } ft := field.Type() + + kind := ft.Kind() + if isPointerKind(kind) { + kind = ft.Elem().Kind() + if !field.IsNil() { + field = reflect.Indirect(field) + } + } switch { - case isValueKind(ft.Kind()): + case isValueKind(kind): addParam(result, tag, omitempty, field) - case ft.Kind() == reflect.Array || ft.Kind() == reflect.Slice: + case kind == reflect.Array || kind == reflect.Slice: if isValueKind(ft.Elem().Kind()) { addListOfParams(result, tag, omitempty, field) } diff --git a/pkg/conversion/queryparams/convert_test.go b/pkg/conversion/queryparams/convert_test.go index 88390a5dcd8..664e128046b 100644 --- a/pkg/conversion/queryparams/convert_test.go +++ b/pkg/conversion/queryparams/convert_test.go @@ -53,6 +53,13 @@ type foo struct { func (*foo) IsAnAPIObject() {} +type baz struct { + Ptr *int `json:"ptr"` + Bptr *bool `json:"bptr,omitempty"` +} + +func (*baz) IsAnAPIObject() {} + func validateResult(t *testing.T, input interface{}, actual, expected url.Values) { local := url.Values{} for k, v := range expected { @@ -131,6 +138,19 @@ func TestConvert(t *testing.T) { }, expected: url.Values{"str": {""}, "namedStr": {"named str"}}, }, + { + input: &baz{ + Ptr: intp(5), + Bptr: boolp(true), + }, + expected: url.Values{"ptr": {"5"}, "bptr": {"true"}}, + }, + { + input: &baz{ + Bptr: boolp(true), + }, + expected: url.Values{"ptr": {""}, "bptr": {"true"}}, + }, } for _, test := range tests { @@ -141,3 +161,7 @@ func TestConvert(t *testing.T) { validateResult(t, test.input, result, test.expected) } } + +func intp(n int) *int { return &n } + +func boolp(b bool) *bool { return &b }