support dereferencing pointers to pointers also update docs to clarify how empty values are handled
diff --git a/query/encode.go b/query/encode.go index dc599a8..3ee37c9 100644 --- a/query/encode.go +++ b/query/encode.go
@@ -21,12 +21,13 @@ package query import ( - "strings" "bytes" + "errors" "fmt" "net/url" "reflect" "strconv" + "strings" "time" ) @@ -37,6 +38,15 @@ // Values expects to be passed a struct, and traverses it recursively using the // following encoding rules. // +// Each exported struct field is encoded as a URL parameter unless +// +// - the field's tag is "-", or +// - the field is empty and its tag specifies the "omitempty" option +// +// The empty values are false, 0, any nil pointer or interface value, any array +// slice, map, or string of length zero, and any time.Time that returns true +// for IsZero(). +// // The URL parameter name defaults to the struct field name but can be // specified in the struct field's tag value. The "url" key in the struct // field's tag value is the key name, followed by an optional comma and @@ -87,11 +97,11 @@ values := &url.Values{} val := reflect.ValueOf(v) - if val.Kind() == reflect.Ptr { + for val.Kind() == reflect.Ptr { if val.IsNil() { - return *values, nil + return nil, errors.New("query: Values() expects non-nil value") } - val = reflect.Indirect(val) + val = val.Elem() } if val.Kind() != reflect.Struct { @@ -171,11 +181,11 @@ // valueString returns the string representation of a value. func valueString(v reflect.Value, opts tagOptions) string { - if v.Kind() == reflect.Ptr { + for v.Kind() == reflect.Ptr { if v.IsNil() { return "" } - v = reflect.Indirect(v) + v = v.Elem() } switch v.Kind() { @@ -200,6 +210,8 @@ return fmt.Sprint(v.Interface()) } +// isEmptyValue checks if a value should be considered empty for the purposes +// of omitting fields with the "omitempty" option. func isEmptyValue(v reflect.Value) bool { switch v.Kind() { case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
diff --git a/query/encode_test.go b/query/encode_test.go index 57b6755..b60a661 100644 --- a/query/encode_test.go +++ b/query/encode_test.go
@@ -13,6 +13,7 @@ func TestValues_types(t *testing.T) { str := "string" + strPtr := &str tests := []struct { in interface{} @@ -40,10 +41,12 @@ struct { A *string B *int - }{A: &str}, + C **string + }{A: strPtr, C: &strPtr}, url.Values{ "A": {str}, "B": {""}, + "C": {str}, }, }, {