Skip to content

Instantly share code, notes, and snippets.

@Blquinn
Created January 23, 2020 04:02
Show Gist options
  • Save Blquinn/88b3cec18ab7cf30b96ce32fa4dffaa5 to your computer and use it in GitHub Desktop.
Save Blquinn/88b3cec18ab7cf30b96ce32fa4dffaa5 to your computer and use it in GitHub Desktop.
Unmarshalling json array into function arguments
package args
import (
"encoding/json"
"errors"
"fmt"
"reflect"
"testing"
)
type testStruct struct {
Foo string `json:"foo"`
}
// You can supply any json serializable value
func fun(i int64, s string, f testStruct) error {
fmt.Printf("i = %d, s = %s, f = %+v", i, s, f)
return nil
}
// Takes a json list and unmarshals the list into
func applyFromJson(fn interface{}, args []json.RawMessage) error {
fv := reflect.ValueOf(fn)
fvt := fv.Type()
if fvt.Kind() != reflect.Func {
return errors.New("fn must be a function")
}
if fvt.NumIn() != len(args) {
return fmt.Errorf("fn expected %d args, %d supplied", fvt.NumIn(), len(args))
}
if fvt.NumOut() != 1 || !fvt.Out(0).Implements(reflect.TypeOf((*error)(nil)).Elem()) {
return errors.New("fn must return an error")
}
in := make([]reflect.Value, fvt.NumIn())
for i := 0; i < fvt.NumIn(); i++ {
fat := fvt.In(i)
nv := reflect.New(fat)
if nv.Elem().Type() != fat {
return fmt.Errorf("argument type %s does not match expected type %s", nv.Elem().Type(), fat)
}
if err := json.Unmarshal(args[i], nv.Interface()); err != nil {
return fmt.Errorf("error unmarshalling argument json: %w", err)
}
in[i] = nv.Elem()
}
err := fv.Call(in)[0].Interface()
if err != nil {
return err.(error)
}
return nil
}
func TestArgsJson(t *testing.T) {
j := []byte(`[10, "foobar", {"foo": "bar"}]`) // This would be arguments in the task json
argsJSON := make([]json.RawMessage, 0)
if err := json.Unmarshal(j, &argsJSON); err != nil {
t.Errorf("failed to unmarshal json: %s", err)
t.FailNow()
}
err := applyFromJson(fun, argsJSON)
if err != nil {
t.Errorf("Failed to apply func: %s", err)
t.FailNow()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment