Skip to content

Commit 4fafd08

Browse files
committed
fixes from upstream
1 parent 35b4e06 commit 4fafd08

File tree

4 files changed

+103
-0
lines changed

4 files changed

+103
-0
lines changed

decoder.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,17 @@ func (d *Decoder) decode(v reflect.Value, path string, parts []pathPart, values
192192
}
193193
v = v.Elem()
194194
}
195+
196+
// alloc embedded structs
197+
if v.Type().Kind() == reflect.Struct {
198+
for i := 0; i < v.NumField(); i++ {
199+
field := v.Field(i)
200+
if field.Type().Kind() == reflect.Ptr && field.IsNil() && v.Type().Field(i).Anonymous == true {
201+
field.Set(reflect.New(field.Type().Elem()))
202+
}
203+
}
204+
}
205+
195206
v = v.FieldByName(name)
196207
}
197208
// Don't even bother for unexported fields.

decoder_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1968,3 +1968,42 @@ func TestTextUnmarshalerEmpty(t *testing.T) {
19681968
t.Errorf("Expected %v errors, got %v", expected, s.Value)
19691969
}
19701970
}
1971+
1972+
type S23n struct {
1973+
F2 string `schema:"F2"`
1974+
F3 string `schema:"F3"`
1975+
}
1976+
1977+
type S23e struct {
1978+
*S23n
1979+
F1 string `schema:"F1"`
1980+
}
1981+
1982+
type S23 []*S23e
1983+
1984+
func TestUnmashalPointerToEmbedded(t *testing.T) {
1985+
data := map[string][]string{
1986+
"A.0.F2": {"raw a"},
1987+
"A.0.F3": {"raw b"},
1988+
}
1989+
1990+
// Implements encoding.TextUnmarshaler, should not throw invalid path
1991+
// error.
1992+
s := struct {
1993+
Value S23 `schema:"A"`
1994+
}{}
1995+
decoder := NewDecoder()
1996+
1997+
if err := decoder.Decode(&s, data); err != nil {
1998+
t.Fatal("Error while decoding:", err)
1999+
}
2000+
2001+
expected := S23{
2002+
&S23e{
2003+
S23n: &S23n{"raw a", "raw b"},
2004+
},
2005+
}
2006+
if !reflect.DeepEqual(expected, s.Value) {
2007+
t.Errorf("Expected %v errors, got %v", expected, s.Value)
2008+
}
2009+
}

encoder.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ func isZero(v reflect.Value) bool {
6262
}
6363
return z
6464
case reflect.Struct:
65+
type zero interface {
66+
IsZero() bool
67+
}
68+
if v.Type().Implements(reflect.TypeOf((*zero)(nil)).Elem()) {
69+
iz := v.MethodByName("IsZero").Call([]reflect.Value{})[0]
70+
return iz.Interface().(bool)
71+
}
6572
z := true
6673
for i := 0; i < v.NumField(); i++ {
6774
z = z && isZero(v.Field(i))

encoder_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"reflect"
66
"testing"
7+
"time"
78
)
89

910
type E1 struct {
@@ -417,3 +418,48 @@ func TestRegisterEncoderCustomArrayType(t *testing.T) {
417418
encoder.Encode(s, vals)
418419
}
419420
}
421+
422+
func TestRegisterEncoderStructIsZero(t *testing.T) {
423+
type S1 struct {
424+
SomeTime1 time.Time `schema:"tim1,omitempty"`
425+
SomeTime2 time.Time `schema:"tim2,omitempty"`
426+
}
427+
428+
ss := []*S1{
429+
{
430+
SomeTime1: time.Date(2020, 8, 4, 13, 30, 1, 0, time.UTC),
431+
},
432+
}
433+
434+
for s := range ss {
435+
vals := map[string][]string{}
436+
437+
encoder := NewEncoder()
438+
encoder.RegisterEncoder(time.Time{}, func(value reflect.Value) string {
439+
return value.Interface().(time.Time).Format(time.RFC3339Nano)
440+
})
441+
442+
err := encoder.Encode(ss[s], vals)
443+
if err != nil {
444+
t.Errorf("Encoder has non-nil error: %v", err)
445+
}
446+
447+
ta, ok := vals["tim1"]
448+
if !ok {
449+
t.Error("expected tim1 to be present")
450+
}
451+
452+
if len(ta) != 1 {
453+
t.Error("expected tim1 to be present")
454+
}
455+
456+
if "2020-08-04T13:30:01Z" != ta[0] {
457+
t.Error("expected correct tim1 time")
458+
}
459+
460+
_, ok = vals["tim2"]
461+
if ok {
462+
t.Error("expected tim1 not to be present")
463+
}
464+
}
465+
}

0 commit comments

Comments
 (0)