Skip to content

Commit 57e3831

Browse files
authored
Merge pull request #3 from jerome-laforge/upstream_master
Improve parseRecursive
2 parents 5441aff + 2202615 commit 57e3831

File tree

4 files changed

+99
-10
lines changed

4 files changed

+99
-10
lines changed

go.mod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module github.com/ryankurte/go-structparse
2+
3+
go 1.12
4+
5+
require (
6+
github.com/stretchr/testify v1.5.1
7+
gopkg.in/yaml.v2 v2.3.0
8+
)

go.sum

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
2+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
5+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
6+
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
7+
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
8+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
9+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
10+
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
11+
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
12+
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

parse.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func parseRecursive(parsers Parsers, val reflect.Value) reflect.Value {
6060
if o.IsValid() {
6161
res := parseRecursive(parsers, o)
6262
if res != reflect.ValueOf(nil) {
63-
return res
63+
return res.Addr()
6464
}
6565
}
6666
case reflect.Interface:
@@ -69,15 +69,23 @@ func parseRecursive(parsers Parsers, val reflect.Value) reflect.Value {
6969
return res
7070
}
7171
case reflect.Struct:
72+
dst := val
73+
if !val.CanSet() {
74+
// this case is typically for a struct in map
75+
dst = reflect.New(val.Type()).Elem()
76+
}
77+
7278
for i := 0; i < val.NumField(); i++ {
79+
if !dst.Field(i).CanSet() {
80+
// this case is typically for unexported field, ignore it
81+
continue
82+
}
7383
res := parseRecursive(parsers, val.Field(i))
7484
if res != reflect.ValueOf(nil) {
75-
if val.Field(i).CanSet() {
76-
val.Field(i).Set(res)
77-
}
85+
dst.Field(i).Set(res)
7886
}
7987
}
80-
return val
88+
return dst
8189
case reflect.Slice:
8290
for i := 0; i < val.Len(); i++ {
8391
res := parseRecursive(parsers, val.Index(i))
@@ -98,7 +106,7 @@ func parseRecursive(parsers Parsers, val reflect.Value) reflect.Value {
98106
}
99107
return val
100108
case reflect.String:
101-
if parsers.StringParser != nil {
109+
if parsers.StringParser != nil && val.Type().AssignableTo(reflect.TypeOf("")) {
102110
value := parsers.StringParser.ParseString(val.String())
103111
return reflect.ValueOf(value)
104112
}

parse_test.go

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package structparse
77

88
import (
99
"testing"
10+
"time"
1011

1112
"github.com/stretchr/testify/assert"
1213
)
@@ -78,10 +79,70 @@ func TestParsing(t *testing.T) {
7879
assert.EqualValues(t, "boop", c.Fake["test2"]["test1"])
7980
})
8081

81-
t.Run("Handles non-supported types", func(t *testing.T) {
82+
t.Run("Handles non-supported types", func(t *testing.T) {
8283
fem := FakeEnvMapper{"TEST", "REPLACED"}
83-
c := struct {Fake bool} { false }
84-
Strings(&fem, &c)
85-
})
84+
c := struct{ Fake bool }{false}
85+
Strings(&fem, &c)
86+
})
87+
88+
t.Run("struct with time", func(t *testing.T) {
89+
fem := FakeEnvMapper{"TEST", "REPLACED"}
90+
type Foo struct {
91+
Bar string
92+
Time time.Time
93+
}
94+
95+
foo := Foo{Bar: "TEST"}
96+
97+
Strings(&fem, &foo)
98+
99+
assert.EqualValues(t, "REPLACED", foo.Bar)
100+
})
101+
102+
t.Run("map", func(t *testing.T) {
103+
fem := FakeEnvMapper{"TEST", "REPLACED"}
104+
type foo struct {
105+
Name string
106+
}
107+
c := map[string]foo{"1": {"TEST"}, "2": {"TEST"}}
108+
109+
Strings(&fem, &c)
110+
111+
assert.EqualValues(t, "REPLACED", c["1"].Name)
112+
assert.EqualValues(t, "REPLACED", c["2"].Name)
113+
})
86114

115+
t.Run("struct", func(t *testing.T) {
116+
fem := FakeEnvMapper{"TEST", "REPLACED"}
117+
type bar struct {
118+
Name string
119+
}
120+
type foo struct {
121+
Bar bar
122+
}
123+
124+
c := foo{Bar: bar{"TEST"}}
125+
126+
Strings(&fem, &c)
127+
128+
assert.EqualValues(t, "REPLACED", c.Bar.Name)
129+
})
130+
131+
t.Run("struct with pointer field", func(t *testing.T) {
132+
fem := FakeEnvMapper{"TEST", "REPLACED"}
133+
type bar struct {
134+
Name string
135+
unexported string
136+
}
137+
type foo struct {
138+
Bar *bar
139+
}
140+
141+
c := foo{Bar: &bar{Name: "TEST", unexported: "unexported"}}
142+
143+
Strings(&fem, &c)
144+
145+
assert.EqualValues(t, "REPLACED", c.Bar.Name)
146+
assert.EqualValues(t, "unexported", c.Bar.unexported)
147+
})
87148
}

0 commit comments

Comments
 (0)