Skip to content

Commit 05266dc

Browse files
committed
allow custom encoders to handle nil pointers
If a custom encoder is defined on a pointer of a type, allow that encoder to handle nil values. Encoders defined on non-pointer types will continue to be given the zero value of the type to encode (the existing behavior). Fixes #46
1 parent 597fdbe commit 05266dc

File tree

2 files changed

+18
-14
lines changed

2 files changed

+18
-14
lines changed

query/encode.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -178,15 +178,10 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error {
178178
continue
179179
}
180180

181-
for sv.Kind() == reflect.Ptr {
182-
if sv.IsNil() {
183-
break
184-
}
185-
sv = sv.Elem()
186-
}
187-
188181
if sv.Type().Implements(encoderType) {
189-
if !reflect.Indirect(sv).IsValid() {
182+
// if sv is a nil pointer and the custom encoder is defined on a non-pointer
183+
// method receiver, set sv to the zero value of the underlying type
184+
if !reflect.Indirect(sv).IsValid() && sv.Type().Elem().Implements(encoderType) {
190185
sv = reflect.New(sv.Type().Elem())
191186
}
192187

@@ -197,6 +192,14 @@ func reflectValue(values url.Values, val reflect.Value, scope string) error {
197192
continue
198193
}
199194

195+
// recursively dereference pointers. break on nil pointers
196+
for sv.Kind() == reflect.Ptr {
197+
if sv.IsNil() {
198+
break
199+
}
200+
sv = sv.Elem()
201+
}
202+
200203
if sv.Kind() == reflect.Slice || sv.Kind() == reflect.Array {
201204
var del string
202205
if opts.Contains("comma") {

query/encode_test.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -553,9 +553,10 @@ type customEncodedIntPtr int
553553
// values cause an error.
554554
func (m *customEncodedIntPtr) EncodeValues(key string, v *url.Values) error {
555555
if m == nil {
556-
return nil
556+
v.Set(key, "undefined")
557+
} else {
558+
v.Set(key, fmt.Sprintf("_%d", *m))
557559
}
558-
v.Set(key, fmt.Sprintf("_%d", *m))
559560
return nil
560561
}
561562

@@ -594,7 +595,7 @@ func TestValues_CustomEncodingPointer(t *testing.T) {
594595
struct {
595596
V *customEncodedIntPtr `url:"v"`
596597
}{},
597-
url.Values{"v": {"_0"}},
598+
url.Values{"v": {"undefined"}},
598599
},
599600
{
600601
struct {
@@ -606,19 +607,19 @@ func TestValues_CustomEncodingPointer(t *testing.T) {
606607
struct {
607608
V *customEncodedIntPtr `url:"v"`
608609
}{&zero},
609-
url.Values{"v": {"0"}},
610+
url.Values{"v": {"_0"}},
610611
},
611612
{
612613
struct {
613614
V *customEncodedIntPtr `url:"v,omitempty"`
614615
}{&zero},
615-
url.Values{"v": {"0"}},
616+
url.Values{"v": {"_0"}},
616617
},
617618
{
618619
struct {
619620
V *customEncodedIntPtr `url:"v"`
620621
}{&one},
621-
url.Values{"v": {"1"}},
622+
url.Values{"v": {"_1"}},
622623
},
623624
}
624625

0 commit comments

Comments
 (0)