Skip to content

Commit be3c511

Browse files
committed
Decode(map[string]interface{})
1 parent 497d0af commit be3c511

File tree

2 files changed

+73
-4
lines changed

2 files changed

+73
-4
lines changed

decode.go

+48-4
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,59 @@ import (
8989
// Field map[string]string `properties:"myName"`
9090
func (p *Properties) Decode(x interface{}) error {
9191
t, v := reflect.TypeOf(x), reflect.ValueOf(x)
92-
if t.Kind() != reflect.Ptr || v.Elem().Type().Kind() != reflect.Struct {
93-
return fmt.Errorf("not a pointer to struct: %s", t)
92+
93+
if isPtr(t) {
94+
elemT := v.Elem().Type()
95+
switch {
96+
case isMap(elemT):
97+
m, ok := x.(*map[string]interface{})
98+
if !ok {
99+
return fmt.Errorf("map type not map[string]interface {}", elemT)
100+
}
101+
if err := p.DecodeToStringMap(*m); err != nil {
102+
return err
103+
}
104+
return nil
105+
106+
case isStruct(elemT):
107+
if err := dec(p, "", nil, nil, v); err != nil {
108+
return err
109+
}
110+
return nil
111+
}
94112
}
95-
if err := dec(p, "", nil, nil, v); err != nil {
96-
return err
113+
114+
return fmt.Errorf("not a pointer to map or struct: %s", t)
115+
}
116+
117+
func (p *Properties) DecodeToStringMap(m map[string]interface{}) error {
118+
for _, key := range p.Keys() {
119+
value, _ := p.Get(key)
120+
setNestedKey(m, key, value)
97121
}
122+
98123
return nil
99124
}
100125

126+
func setNestedKey(m map[string]interface{}, key string, value interface{}) {
127+
if strings.Contains(key, ".") {
128+
kk := strings.SplitN(key, ".", 2)
129+
prefix, rest := kk[0], kk[1]
130+
if _, ok := m[prefix]; !ok {
131+
m[prefix] = make(map[string]interface{})
132+
}
133+
setNestedKey(m[prefix].(map[string]interface{}), rest, value)
134+
} else {
135+
if reflect.TypeOf(value).Kind() == reflect.String {
136+
val := value.(string)
137+
if strings.Contains(val, ";") {
138+
value = split(val, ";")
139+
}
140+
}
141+
m[key] = value
142+
}
143+
}
144+
101145
func dec(p *Properties, key string, def *string, opts map[string]string, v reflect.Value) error {
102146
t := v.Type()
103147

decode_test.go

+25
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,31 @@ func TestDecodeMap(t *testing.T) {
273273
testDecode(t, in, &X{}, out)
274274
}
275275

276+
func TestDecodeToStringMap(t *testing.T) {
277+
type S struct {
278+
A string
279+
}
280+
X := make(map[string]interface{})
281+
in := `
282+
A.foo=bar
283+
A.bar=bang
284+
B.foo=a;b;c
285+
B.bar=1;2;3
286+
C.foo.one=1
287+
C.foo.two=2
288+
C.bar.three=3
289+
C.bar.four=4
290+
D.foo.a=bar
291+
`
292+
out := &map[string]interface{}{
293+
"A": map[string]interface{}{"foo": "bar", "bar": "bang"},
294+
"B": map[string]interface{}{"foo": []string{"a", "b", "c"}, "bar": []string{"1", "2", "3"}},
295+
"C": map[string]interface{}{"foo": map[string]interface{}{"one": "1", "two": "2"}, "bar": map[string]interface{}{"three": "3", "four": "4"}},
296+
"D": map[string]interface{}{"foo": map[string]interface{}{"a": "bar"}},
297+
}
298+
testDecode(t, in, &X, out)
299+
}
300+
276301
func testDecode(t *testing.T, in string, v, out interface{}) {
277302
p, err := parse(in)
278303
if err != nil {

0 commit comments

Comments
 (0)