Skip to content

Commit 632438e

Browse files
committed
Support nested structures in params
flatten function converts nested arrays, slices and maps to flat key-value pairs. The logic is similar to that of python and javascript implementations.
1 parent b87aa09 commit 632438e

File tree

1 file changed

+57
-17
lines changed

1 file changed

+57
-17
lines changed

templates/go/client.go.twig

Lines changed: 57 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -258,23 +258,12 @@ func (clt *Client) Call(method string, path string, headers map[string]interface
258258
return nil, errors.New("invalid input file")
259259
}
260260
}
261-
for key, val := range params {
262-
rt := reflect.TypeOf(val)
263-
switch rt.Kind() {
264-
case reflect.Array:
265-
case reflect.Slice:
266-
arr := reflect.ValueOf(val)
267-
for i := 0; i < arr.Len(); i++ {
268-
err = writer.WriteField(fmt.Sprintf("%s[]", key), toString(arr.Index(i)))
269-
if err != nil {
270-
return nil, err
271-
}
272-
}
273-
default:
274-
err = writer.WriteField(key, toString(val))
275-
if err != nil {
276-
return nil, err
277-
}
261+
flatParams := make(map[string]string)
262+
flatten(params, "", &flatParams)
263+
for key, val := range flatParams {
264+
err = writer.WriteField(key, val)
265+
if err != nil {
266+
return nil, err
278267
}
279268
}
280269
err = writer.Close()
@@ -442,6 +431,12 @@ func toString(arg interface{}) string {
442431
return strconv.FormatFloat(float64(v), 'f', -1, 32)
443432
case float64:
444433
return strconv.FormatFloat(v, 'f', -1, 64)
434+
case bool:
435+
return strconv.FormatBool(v)
436+
case complex64:
437+
return strconv.FormatComplex(complex128(v), 'f', -1, 64)
438+
case complex128:
439+
return strconv.FormatComplex(v, 'f', -1, 128)
445440
case reflect.Value:
446441
return toString(v.Interface())
447442
case fmt.Stringer:
@@ -450,3 +445,48 @@ func toString(arg interface{}) string {
450445
return fmt.Sprintf("%s", v)
451446
}
452447
}
448+
449+
// flatten recursively flattens params into a map[string]string and writes it to result
450+
func flatten(params interface{}, prefix string, result *map[string]string) error {
451+
if result == nil {
452+
return errors.New("result is nil")
453+
}
454+
455+
paramsType := reflect.TypeOf(params)
456+
if paramsType.Kind() == reflect.Pointer {
457+
paramsType = paramsType.Elem()
458+
}
459+
switch paramsType.Kind() {
460+
case reflect.Array:
461+
fallthrough
462+
case reflect.Slice:
463+
arr := reflect.Indirect(reflect.ValueOf(params))
464+
for i := 0; i < arr.Len(); i++ {
465+
currentPrefix := fmt.Sprintf("%s[%d]", prefix, i)
466+
err := flatten(arr.Index(i).Interface(), currentPrefix, result)
467+
if err != nil {
468+
return err
469+
}
470+
}
471+
case reflect.Map:
472+
m := reflect.Indirect(reflect.ValueOf(params))
473+
for _, key := range m.MapKeys() {
474+
var currentPrefix string
475+
if prefix == "" {
476+
currentPrefix = toString(key)
477+
} else {
478+
currentPrefix = fmt.Sprintf("%s[%s]", prefix, toString(key))
479+
}
480+
err := flatten(m.MapIndex(key).Interface(), currentPrefix, result)
481+
if err != nil {
482+
return err
483+
}
484+
}
485+
default:
486+
if prefix == "" {
487+
return fmt.Errorf("prefix is empty for %s", params)
488+
}
489+
(*result)[prefix] = toString(params)
490+
}
491+
return nil
492+
}

0 commit comments

Comments
 (0)