From 5fa9f6b463fc2a66a125ccdbb8fbf607e50d7997 Mon Sep 17 00:00:00 2001 From: themihai Date: Wed, 6 Jul 2016 16:36:40 +0300 Subject: [PATCH] feat(Enc): allows the caller to change the tag used to locate custom field aliases --- query/encode.go | 36 ++++++++++++++++++++++++++++++------ query/encode_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/query/encode.go b/query/encode.go index 19437b3..abecb7a 100644 --- a/query/encode.go +++ b/query/encode.go @@ -110,7 +110,12 @@ type Encoder interface { // // Multiple fields that encode to the same URL parameter name will be included // as multiple URL values of the same name. + func Values(v interface{}) (url.Values, error) { + return values(v, "url") +} + +func values(v interface{}, tag string) (url.Values, error) { values := make(url.Values) val := reflect.ValueOf(v) for val.Kind() == reflect.Ptr { @@ -128,14 +133,33 @@ func Values(v interface{}) (url.Values, error) { return nil, fmt.Errorf("query: Values() expects struct input. Got %v", val.Kind()) } - err := reflectValue(values, val, "") - return values, err + err := reflectValue(values, val, "", tag) + return values, err +} + + +type Enc struct{ + tag string } +func NewEncoder()*Enc{ + return &Enc{tag: "url"} +} + +// SetAliasTag changes the tag used to locate custom field aliases. The default tag is "url". +func(e *Enc)SetAliasTag(tag string)*Enc{ + e.tag = tag + return e +} + +func (e *Enc)Values(v interface{}) (url.Values, error){ + return values(v, e.tag) +} + // reflectValue populates the values parameter from the struct fields in val. // Embedded structs are followed recursively (using the rules defined in the // Values function documentation) breadth-first. -func reflectValue(values url.Values, val reflect.Value, scope string) error { +func reflectValue(values url.Values, val reflect.Value, scope, tagSel string) error { var embedded []reflect.Value typ := val.Type() @@ -146,7 +170,7 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { } sv := val.Field(i) - tag := sf.Tag.Get("url") + tag := sf.Tag.Get(tagSel) if tag == "-" { continue } @@ -230,7 +254,7 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { } if sv.Kind() == reflect.Struct { - reflectValue(values, sv, name) + reflectValue(values, sv, name, tagSel) continue } @@ -238,7 +262,7 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error { } for _, f := range embedded { - if err := reflectValue(values, f, scope); err != nil { + if err := reflectValue(values, f, scope, tagSel); err != nil { return err } } diff --git a/query/encode_test.go b/query/encode_test.go index da4c074..dba6250 100644 --- a/query/encode_test.go +++ b/query/encode_test.go @@ -171,6 +171,42 @@ func TestValues_types(t *testing.T) { } } +func TestEnc(t *testing.T){ + var tests = []struct{ + in interface{} + want url.Values + }{ + { + in: struct{ + C []string `xyz:"a"` + }{ + C: []string{"a", "b"}, + }, + want: url.Values{"a": {"a", "b"},}, + }, + { + in: struct{ + C []string + }{ + C: []string{"a", "b"}, + }, + want: url.Values{"C": {"a", "b"},}, + }, + + } + for i, tt := range tests { + en := NewEncoder().SetAliasTag("xyz") + v, err := en.Values(tt.in) + if err != nil { + t.Errorf("%d. Values(%q) returned error: %v", i, tt.in, err) + } + + if !reflect.DeepEqual(tt.want, v) { + t.Errorf("%d. Enc(%q) returned %v, want %v", i, tt.in, v, tt.want) + } + } +} + func TestValues_omitEmpty(t *testing.T) { str := "" s := struct {