Better support for array and struct serialization

This patch allows better encoding of nested structs and arrays to follow
[conventions followed by frameworks like Rails][1] when parsing query
strings such as ```ids[]=1&ids[]=2&ids[]=3``` for arrays and
```user[name]=acme&user[addr][postcode]=1234&user[addr][city]=SFO``` for
hashes.

Changes:

 * Encode nested attributes: ```Parameter.Nested.Value = "str"``` would
 be encoded as ```parameter[nested][value]=str```
 * New ```brackets``` tag option for arrays so that in stead of encoding
 an array as ```a=one&a=two``` it's encoded as ```a[]=one&a[]=two```
 which are read

[1]: http://guides.rubyonrails.org/action_controller_overview.html#hash-and-array-parameters
diff --git a/query/encode.go b/query/encode.go
index 31d36e7..396d804 100644
--- a/query/encode.go
+++ b/query/encode.go
@@ -22,7 +22,6 @@
 
 import (
 	"bytes"
-	"errors"
 	"fmt"
 	"net/url"
 	"reflect"
@@ -88,7 +87,9 @@
 // Slice and Array values default to encoding as multiple URL values of the
 // same name.  Including the "comma" option signals that the field should be
 // encoded as a single comma-delimited value.  Including the "space" option
-// similarly encodes the value as a single space-delimited string.
+// similarly encodes the value as a single space-delimited string. Including
+// the "brackets" option signals that the multiple URL values should have "[]"
+// appended to the value name.
 //
 // Anonymous struct fields are usually encoded as if their inner exported
 // fields were fields in the outer struct, subject to the standard Go
@@ -97,32 +98,41 @@
 //
 // Non-nil pointer values are encoded as the value pointed to.
 //
+// Nested structs are encoded including parent fields in value names for
+// scoping. e.g:
+//
+// 	"user[name]=acme&user[addr][postcode]=1234&user[addr][city]=SFO"
+//
 // All other values are encoded using their default string representation.
 //
 // 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) {
+	values := make(url.Values)
 	val := reflect.ValueOf(v)
 	for val.Kind() == reflect.Ptr {
 		if val.IsNil() {
-			return nil, errors.New("query: Values() expects non-nil value")
+			return values, nil
 		}
 		val = val.Elem()
 	}
 
+	if v == nil {
+		return values, nil
+	}
+
 	if val.Kind() != reflect.Struct {
 		return nil, fmt.Errorf("query: Values() expects struct input. Got %v", val.Kind())
 	}
 
-	values := make(url.Values)
-	err := reflectValue(values, val)
+	err := reflectValue(values, val, "")
 	return values, err
 }
 
 // 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) error {
+func reflectValue(values url.Values, val reflect.Value, scope string) error {
 	var embedded []reflect.Value
 
 	typ := val.Type()
@@ -148,6 +158,10 @@
 			name = sf.Name
 		}
 
+		if scope != "" {
+			name = scope + "[" + name + "]"
+		}
+
 		if opts.Contains("omitempty") && isEmptyValue(sv) {
 			continue
 		}
@@ -166,6 +180,8 @@
 				del = ','
 			} else if opts.Contains("space") {
 				del = ' '
+			} else if opts.Contains("brackets") {
+				name = name + "[]"
 			}
 
 			if del != 0 {
@@ -188,11 +204,28 @@
 			continue
 		}
 
+		if sv.Type() == timeType {
+			values.Add(name, valueString(sv, opts))
+			continue
+		}
+
+		for sv.Kind() == reflect.Ptr {
+			if sv.IsNil() {
+				break
+			}
+			sv = sv.Elem()
+		}
+
+		if sv.Kind() == reflect.Struct {
+			reflectValue(values, sv, name)
+			continue
+		}
+
 		values.Add(name, valueString(sv, opts))
 	}
 
 	for _, f := range embedded {
-		if err := reflectValue(values, f); err != nil {
+		if err := reflectValue(values, f, scope); err != nil {
 			return err
 		}
 	}
diff --git a/query/encode_test.go b/query/encode_test.go
index 8afbd0b..09efb0f 100644
--- a/query/encode_test.go
+++ b/query/encode_test.go
@@ -12,6 +12,16 @@
 	"time"
 )
 
+type Nested struct {
+	A   SubNested  `url:"a"`
+	B   *SubNested `url:"b"`
+	Ptr *SubNested `url:"ptr,omitempty"`
+}
+
+type SubNested struct {
+	Value string `url:"value"`
+}
+
 func TestValues_types(t *testing.T) {
 	str := "string"
 	strPtr := &str
@@ -61,6 +71,7 @@
 				F [2]string `url:",space"`
 				G []*string `url:",space"`
 				H []bool    `url:",int,space"`
+				I []string  `url:",brackets"`
 			}{
 				A: []string{"a", "b"},
 				B: []string{"a", "b"},
@@ -70,16 +81,18 @@
 				F: [2]string{"a", "b"},
 				G: []*string{&str, &str},
 				H: []bool{true, false},
+				I: []string{"a", "b"},
 			},
 			url.Values{
-				"A": {"a", "b"},
-				"B": {"a,b"},
-				"C": {"a b"},
-				"D": {"a", "b"},
-				"E": {"a,b"},
-				"F": {"a b"},
-				"G": {"string string"},
-				"H": {"1 0"},
+				"A":   {"a", "b"},
+				"B":   {"a,b"},
+				"C":   {"a b"},
+				"D":   {"a", "b"},
+				"E":   {"a,b"},
+				"F":   {"a b"},
+				"G":   {"string string"},
+				"H":   {"1 0"},
+				"I[]": {"a", "b"},
 			},
 		},
 		{
@@ -102,6 +115,41 @@
 				"D": {"0"},
 			},
 		},
+		{
+			struct {
+				Nest Nested `url:"nest"`
+			}{
+				Nested{
+					A: SubNested{
+						Value: "that",
+					},
+				},
+			},
+			url.Values{
+				"nest[a][value]": {"that"},
+				"nest[b]":        {""},
+			},
+		},
+		{
+			struct {
+				Nest Nested `url:"nest"`
+			}{
+				Nested{
+					Ptr: &SubNested{
+						Value: "that",
+					},
+				},
+			},
+			url.Values{
+				"nest[a][value]":   {""},
+				"nest[b]":          {""},
+				"nest[ptr][value]": {"that"},
+			},
+		},
+		{
+			nil,
+			url.Values{},
+		},
 	}
 
 	for i, tt := range tests {