@@ -3,9 +3,210 @@ package encoding
3
3
import (
4
4
"fmt"
5
5
"reflect"
6
+ "strconv"
6
7
"strings"
7
8
)
8
9
10
+ func convertStruct (i interface {}, t reflect.Type , pointer bool ) (reflect.Value , error ) {
11
+ m , ok := i .(map [string ]interface {})
12
+ if ! ok {
13
+ return zeroValue , fmt .Errorf ("Cannot convert %T to struct" , i )
14
+ }
15
+
16
+ out := reflect .New (t )
17
+
18
+ err := Unstringify (m , out .Interface ())
19
+ if err != nil {
20
+ return zeroValue , err
21
+ }
22
+
23
+ if ! pointer {
24
+ out = out .Elem ()
25
+ }
26
+
27
+ return out , nil
28
+ }
29
+
30
+ func convertSlice (i interface {}, t reflect.Type , pointer bool ) (reflect.Value , error ) {
31
+ s , ok := i .([]interface {})
32
+ if ! ok {
33
+ return zeroValue , fmt .Errorf ("Cannot convert %T to slice" , i )
34
+ }
35
+
36
+ out := reflect .New (t )
37
+ out .Elem ().Set (reflect .MakeSlice (t , len (s ), len (s )))
38
+
39
+ for j , v := range s {
40
+ val , err := convertType (t .Elem (), v )
41
+ if err != nil {
42
+ return zeroValue , err
43
+ }
44
+
45
+ out .Elem ().Index (j ).Set (val )
46
+ }
47
+
48
+ if ! pointer {
49
+ out = out .Elem ()
50
+ }
51
+
52
+ return out , nil
53
+ }
54
+
55
+ func convertMap (i interface {}, t reflect.Type , pointer bool ) (reflect.Value , error ) {
56
+ m , ok := i .(map [string ]interface {})
57
+ if ! ok {
58
+ return zeroValue , fmt .Errorf ("Cannot convert %T to map with string keys" , i )
59
+ }
60
+
61
+ out := reflect .New (t )
62
+ out .Elem ().Set (reflect .MakeMap (t ))
63
+
64
+ for k , v := range m {
65
+ val , err := convertType (t .Elem (), v )
66
+ if err != nil {
67
+ return zeroValue , err
68
+ }
69
+
70
+ out .Elem ().SetMapIndex (reflect .ValueOf (k ), val )
71
+ }
72
+
73
+ if ! pointer {
74
+ out = out .Elem ()
75
+ }
76
+
77
+ return out , nil
78
+ }
79
+
80
+ func convertString (i interface {}, pointer bool ) (reflect.Value , error ) {
81
+ s , ok := i .(string )
82
+
83
+ if ! ok {
84
+ return zeroValue , fmt .Errorf ("Cannot convert %T to string" , i )
85
+ }
86
+
87
+ if pointer {
88
+ return reflect .ValueOf (& s ), nil
89
+ }
90
+
91
+ return reflect .ValueOf (s ), nil
92
+ }
93
+
94
+ func convertBool (i interface {}, pointer bool ) (reflect.Value , error ) {
95
+ var b bool
96
+ var err error
97
+
98
+ switch v := i .(type ) {
99
+ case bool :
100
+ b = v
101
+
102
+ case string :
103
+ b , err = strconv .ParseBool (v )
104
+ if err != nil {
105
+ return zeroValue , err
106
+ }
107
+
108
+ default :
109
+ return zeroValue , fmt .Errorf ("Cannot convert %T to bool" , i )
110
+ }
111
+
112
+ if pointer {
113
+ return reflect .ValueOf (& b ), nil
114
+ }
115
+
116
+ return reflect .ValueOf (b ), nil
117
+ }
118
+
119
+ func convertInt (i interface {}, pointer bool ) (reflect.Value , error ) {
120
+ var n int
121
+
122
+ switch v := i .(type ) {
123
+ case int :
124
+ n = v
125
+
126
+ case float64 :
127
+ n = int (v )
128
+
129
+ case string :
130
+ n64 , err := strconv .ParseInt (v , 0 , 32 )
131
+ if err != nil {
132
+ return zeroValue , err
133
+ }
134
+
135
+ n = int (n64 )
136
+
137
+ default :
138
+ return zeroValue , fmt .Errorf ("Cannot convert %T to bool" , i )
139
+ }
140
+
141
+ if pointer {
142
+ return reflect .ValueOf (& n ), nil
143
+ }
144
+
145
+ return reflect .ValueOf (n ), nil
146
+ }
147
+
148
+ func convertFloat64 (i interface {}, pointer bool ) (reflect.Value , error ) {
149
+ var f float64
150
+ var err error
151
+
152
+ switch v := i .(type ) {
153
+ case float64 :
154
+ f = v
155
+
156
+ case int :
157
+ f = float64 (v )
158
+
159
+ case string :
160
+ f , err = strconv .ParseFloat (v , 64 )
161
+ if err != nil {
162
+ return zeroValue , err
163
+ }
164
+
165
+ default :
166
+ return zeroValue , fmt .Errorf ("Cannot convert %T to bool" , i )
167
+ }
168
+
169
+ if pointer {
170
+ return reflect .ValueOf (& f ), nil
171
+ }
172
+
173
+ return reflect .ValueOf (f ), nil
174
+ }
175
+
176
+ func convertType (t reflect.Type , i interface {}) (reflect.Value , error ) {
177
+ pointer := false
178
+ if t .Kind () == reflect .Ptr {
179
+ pointer = true
180
+ t = t .Elem ()
181
+ }
182
+
183
+ switch t .Kind () {
184
+ case reflect .Struct :
185
+ return convertStruct (i , t , pointer )
186
+
187
+ case reflect .Slice :
188
+ return convertSlice (i , t , pointer )
189
+
190
+ case reflect .Map :
191
+ return convertMap (i , t , pointer )
192
+
193
+ case reflect .String :
194
+ return convertString (i , pointer )
195
+
196
+ case reflect .Bool :
197
+ return convertBool (i , pointer )
198
+
199
+ case reflect .Int :
200
+ return convertInt (i , pointer )
201
+
202
+ case reflect .Float64 :
203
+ return convertFloat64 (i , pointer )
204
+
205
+ default :
206
+ return zeroValue , fmt .Errorf ("Unsupported type %v" , t )
207
+ }
208
+ }
209
+
9
210
// Unstringify takes a stringified representation of a value
10
211
// and populates it into the supplied interface
11
212
func Unstringify (data map [string ]interface {}, v interface {}) error {
@@ -22,38 +223,10 @@ func Unstringify(data map[string]interface{}, v interface{}) error {
22
223
jsonName = jsonTag [0 ]
23
224
}
24
225
25
- var newValue reflect.Value
26
-
27
226
if value , ok := data [jsonName ]; ok {
28
- switch f .Type .Kind () {
29
- case reflect .Ptr :
30
- switch f .Type .Elem ().Kind () {
31
- case reflect .String :
32
- newValue = toStringPtrValue (value .(string ))
33
- case reflect .Bool :
34
- newValue = toBoolPtrValue (value .(string ))
35
- case reflect .Int :
36
- newValue = toIntPtrValue (value .(string ))
37
- case reflect .Float64 :
38
- newValue = toFloat64PtrValue (value .(string ))
39
- case reflect .Struct :
40
- newValue = reflect .New (f .Type .Elem ())
41
- Unstringify (value .(map [string ]interface {}), newValue .Interface ())
42
- }
43
- case reflect .String :
44
- newValue = toStringValue (value .(string ))
45
- case reflect .Bool :
46
- newValue = toBoolValue (value .(string ))
47
- case reflect .Int :
48
- newValue = toIntValue (value .(string ))
49
- case reflect .Float64 :
50
- newValue = toFloat64Value (value .(string ))
51
- case reflect .Struct :
52
- newValue = reflect .New (f .Type )
53
- Unstringify (value .(map [string ]interface {}), newValue .Interface ())
54
- newValue = newValue .Elem ()
55
- default :
56
- return fmt .Errorf ("Unsupported type: '%v'" , f .Type )
227
+ newValue , err := convertType (f .Type , value )
228
+ if err != nil {
229
+ return err
57
230
}
58
231
59
232
val .FieldByName (f .Name ).Set (newValue )
0 commit comments