|
1 // Package mapstructure exposes functionality to convert an arbitrary |
|
2 // map[string]interface{} into a native Go structure. |
|
3 // |
|
4 // The Go structure can be arbitrarily complex, containing slices, |
|
5 // other structs, etc. and the decoder will properly decode nested |
|
6 // maps and so on into the proper structures in the native Go struct. |
|
7 // See the examples to see what the decoder is capable of. |
|
8 package mapstructure |
|
9 |
|
10 import ( |
|
11 "encoding/json" |
|
12 "errors" |
|
13 "fmt" |
|
14 "reflect" |
|
15 "sort" |
|
16 "strconv" |
|
17 "strings" |
|
18 ) |
|
19 |
|
20 // DecodeHookFunc is the callback function that can be used for |
|
21 // data transformations. See "DecodeHook" in the DecoderConfig |
|
22 // struct. |
|
23 // |
|
24 // The type should be DecodeHookFuncType or DecodeHookFuncKind. |
|
25 // Either is accepted. Types are a superset of Kinds (Types can return |
|
26 // Kinds) and are generally a richer thing to use, but Kinds are simpler |
|
27 // if you only need those. |
|
28 // |
|
29 // The reason DecodeHookFunc is multi-typed is for backwards compatibility: |
|
30 // we started with Kinds and then realized Types were the better solution, |
|
31 // but have a promise to not break backwards compat so we now support |
|
32 // both. |
|
33 type DecodeHookFunc interface{} |
|
34 |
|
35 // DecodeHookFuncType is a DecodeHookFunc which has complete information about |
|
36 // the source and target types. |
|
37 type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) |
|
38 |
|
39 // DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the |
|
40 // source and target types. |
|
41 type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) |
|
42 |
|
43 // DecoderConfig is the configuration that is used to create a new decoder |
|
44 // and allows customization of various aspects of decoding. |
|
45 type DecoderConfig struct { |
|
46 // DecodeHook, if set, will be called before any decoding and any |
|
47 // type conversion (if WeaklyTypedInput is on). This lets you modify |
|
48 // the values before they're set down onto the resulting struct. |
|
49 // |
|
50 // If an error is returned, the entire decode will fail with that |
|
51 // error. |
|
52 DecodeHook DecodeHookFunc |
|
53 |
|
54 // If ErrorUnused is true, then it is an error for there to exist |
|
55 // keys in the original map that were unused in the decoding process |
|
56 // (extra keys). |
|
57 ErrorUnused bool |
|
58 |
|
59 // ZeroFields, if set to true, will zero fields before writing them. |
|
60 // For example, a map will be emptied before decoded values are put in |
|
61 // it. If this is false, a map will be merged. |
|
62 ZeroFields bool |
|
63 |
|
64 // If WeaklyTypedInput is true, the decoder will make the following |
|
65 // "weak" conversions: |
|
66 // |
|
67 // - bools to string (true = "1", false = "0") |
|
68 // - numbers to string (base 10) |
|
69 // - bools to int/uint (true = 1, false = 0) |
|
70 // - strings to int/uint (base implied by prefix) |
|
71 // - int to bool (true if value != 0) |
|
72 // - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F, |
|
73 // FALSE, false, False. Anything else is an error) |
|
74 // - empty array = empty map and vice versa |
|
75 // - negative numbers to overflowed uint values (base 10) |
|
76 // - slice of maps to a merged map |
|
77 // - single values are converted to slices if required. Each |
|
78 // element is weakly decoded. For example: "4" can become []int{4} |
|
79 // if the target type is an int slice. |
|
80 // |
|
81 WeaklyTypedInput bool |
|
82 |
|
83 // Metadata is the struct that will contain extra metadata about |
|
84 // the decoding. If this is nil, then no metadata will be tracked. |
|
85 Metadata *Metadata |
|
86 |
|
87 // Result is a pointer to the struct that will contain the decoded |
|
88 // value. |
|
89 Result interface{} |
|
90 |
|
91 // The tag name that mapstructure reads for field names. This |
|
92 // defaults to "mapstructure" |
|
93 TagName string |
|
94 } |
|
95 |
|
96 // A Decoder takes a raw interface value and turns it into structured |
|
97 // data, keeping track of rich error information along the way in case |
|
98 // anything goes wrong. Unlike the basic top-level Decode method, you can |
|
99 // more finely control how the Decoder behaves using the DecoderConfig |
|
100 // structure. The top-level Decode method is just a convenience that sets |
|
101 // up the most basic Decoder. |
|
102 type Decoder struct { |
|
103 config *DecoderConfig |
|
104 } |
|
105 |
|
106 // Metadata contains information about decoding a structure that |
|
107 // is tedious or difficult to get otherwise. |
|
108 type Metadata struct { |
|
109 // Keys are the keys of the structure which were successfully decoded |
|
110 Keys []string |
|
111 |
|
112 // Unused is a slice of keys that were found in the raw value but |
|
113 // weren't decoded since there was no matching field in the result interface |
|
114 Unused []string |
|
115 } |
|
116 |
|
117 // Decode takes an input structure and uses reflection to translate it to |
|
118 // the output structure. output must be a pointer to a map or struct. |
|
119 func Decode(input interface{}, output interface{}) error { |
|
120 config := &DecoderConfig{ |
|
121 Metadata: nil, |
|
122 Result: output, |
|
123 } |
|
124 |
|
125 decoder, err := NewDecoder(config) |
|
126 if err != nil { |
|
127 return err |
|
128 } |
|
129 |
|
130 return decoder.Decode(input) |
|
131 } |
|
132 |
|
133 // WeakDecode is the same as Decode but is shorthand to enable |
|
134 // WeaklyTypedInput. See DecoderConfig for more info. |
|
135 func WeakDecode(input, output interface{}) error { |
|
136 config := &DecoderConfig{ |
|
137 Metadata: nil, |
|
138 Result: output, |
|
139 WeaklyTypedInput: true, |
|
140 } |
|
141 |
|
142 decoder, err := NewDecoder(config) |
|
143 if err != nil { |
|
144 return err |
|
145 } |
|
146 |
|
147 return decoder.Decode(input) |
|
148 } |
|
149 |
|
150 // DecodeMetadata is the same as Decode, but is shorthand to |
|
151 // enable metadata collection. See DecoderConfig for more info. |
|
152 func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { |
|
153 config := &DecoderConfig{ |
|
154 Metadata: metadata, |
|
155 Result: output, |
|
156 } |
|
157 |
|
158 decoder, err := NewDecoder(config) |
|
159 if err != nil { |
|
160 return err |
|
161 } |
|
162 |
|
163 return decoder.Decode(input) |
|
164 } |
|
165 |
|
166 // WeakDecodeMetadata is the same as Decode, but is shorthand to |
|
167 // enable both WeaklyTypedInput and metadata collection. See |
|
168 // DecoderConfig for more info. |
|
169 func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { |
|
170 config := &DecoderConfig{ |
|
171 Metadata: metadata, |
|
172 Result: output, |
|
173 WeaklyTypedInput: true, |
|
174 } |
|
175 |
|
176 decoder, err := NewDecoder(config) |
|
177 if err != nil { |
|
178 return err |
|
179 } |
|
180 |
|
181 return decoder.Decode(input) |
|
182 } |
|
183 |
|
184 // NewDecoder returns a new decoder for the given configuration. Once |
|
185 // a decoder has been returned, the same configuration must not be used |
|
186 // again. |
|
187 func NewDecoder(config *DecoderConfig) (*Decoder, error) { |
|
188 val := reflect.ValueOf(config.Result) |
|
189 if val.Kind() != reflect.Ptr { |
|
190 return nil, errors.New("result must be a pointer") |
|
191 } |
|
192 |
|
193 val = val.Elem() |
|
194 if !val.CanAddr() { |
|
195 return nil, errors.New("result must be addressable (a pointer)") |
|
196 } |
|
197 |
|
198 if config.Metadata != nil { |
|
199 if config.Metadata.Keys == nil { |
|
200 config.Metadata.Keys = make([]string, 0) |
|
201 } |
|
202 |
|
203 if config.Metadata.Unused == nil { |
|
204 config.Metadata.Unused = make([]string, 0) |
|
205 } |
|
206 } |
|
207 |
|
208 if config.TagName == "" { |
|
209 config.TagName = "mapstructure" |
|
210 } |
|
211 |
|
212 result := &Decoder{ |
|
213 config: config, |
|
214 } |
|
215 |
|
216 return result, nil |
|
217 } |
|
218 |
|
219 // Decode decodes the given raw interface to the target pointer specified |
|
220 // by the configuration. |
|
221 func (d *Decoder) Decode(input interface{}) error { |
|
222 return d.decode("", input, reflect.ValueOf(d.config.Result).Elem()) |
|
223 } |
|
224 |
|
225 // Decodes an unknown data type into a specific reflection value. |
|
226 func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error { |
|
227 if input == nil { |
|
228 // If the data is nil, then we don't set anything, unless ZeroFields is set |
|
229 // to true. |
|
230 if d.config.ZeroFields { |
|
231 outVal.Set(reflect.Zero(outVal.Type())) |
|
232 |
|
233 if d.config.Metadata != nil && name != "" { |
|
234 d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) |
|
235 } |
|
236 } |
|
237 return nil |
|
238 } |
|
239 |
|
240 inputVal := reflect.ValueOf(input) |
|
241 if !inputVal.IsValid() { |
|
242 // If the input value is invalid, then we just set the value |
|
243 // to be the zero value. |
|
244 outVal.Set(reflect.Zero(outVal.Type())) |
|
245 if d.config.Metadata != nil && name != "" { |
|
246 d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) |
|
247 } |
|
248 return nil |
|
249 } |
|
250 |
|
251 if d.config.DecodeHook != nil { |
|
252 // We have a DecodeHook, so let's pre-process the input. |
|
253 var err error |
|
254 input, err = DecodeHookExec( |
|
255 d.config.DecodeHook, |
|
256 inputVal.Type(), outVal.Type(), input) |
|
257 if err != nil { |
|
258 return fmt.Errorf("error decoding '%s': %s", name, err) |
|
259 } |
|
260 } |
|
261 |
|
262 var err error |
|
263 inputKind := getKind(outVal) |
|
264 switch inputKind { |
|
265 case reflect.Bool: |
|
266 err = d.decodeBool(name, input, outVal) |
|
267 case reflect.Interface: |
|
268 err = d.decodeBasic(name, input, outVal) |
|
269 case reflect.String: |
|
270 err = d.decodeString(name, input, outVal) |
|
271 case reflect.Int: |
|
272 err = d.decodeInt(name, input, outVal) |
|
273 case reflect.Uint: |
|
274 err = d.decodeUint(name, input, outVal) |
|
275 case reflect.Float32: |
|
276 err = d.decodeFloat(name, input, outVal) |
|
277 case reflect.Struct: |
|
278 err = d.decodeStruct(name, input, outVal) |
|
279 case reflect.Map: |
|
280 err = d.decodeMap(name, input, outVal) |
|
281 case reflect.Ptr: |
|
282 err = d.decodePtr(name, input, outVal) |
|
283 case reflect.Slice: |
|
284 err = d.decodeSlice(name, input, outVal) |
|
285 case reflect.Array: |
|
286 err = d.decodeArray(name, input, outVal) |
|
287 case reflect.Func: |
|
288 err = d.decodeFunc(name, input, outVal) |
|
289 default: |
|
290 // If we reached this point then we weren't able to decode it |
|
291 return fmt.Errorf("%s: unsupported type: %s", name, inputKind) |
|
292 } |
|
293 |
|
294 // If we reached here, then we successfully decoded SOMETHING, so |
|
295 // mark the key as used if we're tracking metainput. |
|
296 if d.config.Metadata != nil && name != "" { |
|
297 d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) |
|
298 } |
|
299 |
|
300 return err |
|
301 } |
|
302 |
|
303 // This decodes a basic type (bool, int, string, etc.) and sets the |
|
304 // value to "data" of that type. |
|
305 func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { |
|
306 if val.IsValid() && val.Elem().IsValid() { |
|
307 return d.decode(name, data, val.Elem()) |
|
308 } |
|
309 dataVal := reflect.ValueOf(data) |
|
310 if !dataVal.IsValid() { |
|
311 dataVal = reflect.Zero(val.Type()) |
|
312 } |
|
313 |
|
314 dataValType := dataVal.Type() |
|
315 if !dataValType.AssignableTo(val.Type()) { |
|
316 return fmt.Errorf( |
|
317 "'%s' expected type '%s', got '%s'", |
|
318 name, val.Type(), dataValType) |
|
319 } |
|
320 |
|
321 val.Set(dataVal) |
|
322 return nil |
|
323 } |
|
324 |
|
325 func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { |
|
326 dataVal := reflect.ValueOf(data) |
|
327 dataKind := getKind(dataVal) |
|
328 |
|
329 converted := true |
|
330 switch { |
|
331 case dataKind == reflect.String: |
|
332 val.SetString(dataVal.String()) |
|
333 case dataKind == reflect.Bool && d.config.WeaklyTypedInput: |
|
334 if dataVal.Bool() { |
|
335 val.SetString("1") |
|
336 } else { |
|
337 val.SetString("0") |
|
338 } |
|
339 case dataKind == reflect.Int && d.config.WeaklyTypedInput: |
|
340 val.SetString(strconv.FormatInt(dataVal.Int(), 10)) |
|
341 case dataKind == reflect.Uint && d.config.WeaklyTypedInput: |
|
342 val.SetString(strconv.FormatUint(dataVal.Uint(), 10)) |
|
343 case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: |
|
344 val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64)) |
|
345 case dataKind == reflect.Slice && d.config.WeaklyTypedInput, |
|
346 dataKind == reflect.Array && d.config.WeaklyTypedInput: |
|
347 dataType := dataVal.Type() |
|
348 elemKind := dataType.Elem().Kind() |
|
349 switch elemKind { |
|
350 case reflect.Uint8: |
|
351 var uints []uint8 |
|
352 if dataKind == reflect.Array { |
|
353 uints = make([]uint8, dataVal.Len(), dataVal.Len()) |
|
354 for i := range uints { |
|
355 uints[i] = dataVal.Index(i).Interface().(uint8) |
|
356 } |
|
357 } else { |
|
358 uints = dataVal.Interface().([]uint8) |
|
359 } |
|
360 val.SetString(string(uints)) |
|
361 default: |
|
362 converted = false |
|
363 } |
|
364 default: |
|
365 converted = false |
|
366 } |
|
367 |
|
368 if !converted { |
|
369 return fmt.Errorf( |
|
370 "'%s' expected type '%s', got unconvertible type '%s'", |
|
371 name, val.Type(), dataVal.Type()) |
|
372 } |
|
373 |
|
374 return nil |
|
375 } |
|
376 |
|
377 func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { |
|
378 dataVal := reflect.ValueOf(data) |
|
379 dataKind := getKind(dataVal) |
|
380 dataType := dataVal.Type() |
|
381 |
|
382 switch { |
|
383 case dataKind == reflect.Int: |
|
384 val.SetInt(dataVal.Int()) |
|
385 case dataKind == reflect.Uint: |
|
386 val.SetInt(int64(dataVal.Uint())) |
|
387 case dataKind == reflect.Float32: |
|
388 val.SetInt(int64(dataVal.Float())) |
|
389 case dataKind == reflect.Bool && d.config.WeaklyTypedInput: |
|
390 if dataVal.Bool() { |
|
391 val.SetInt(1) |
|
392 } else { |
|
393 val.SetInt(0) |
|
394 } |
|
395 case dataKind == reflect.String && d.config.WeaklyTypedInput: |
|
396 i, err := strconv.ParseInt(dataVal.String(), 0, val.Type().Bits()) |
|
397 if err == nil { |
|
398 val.SetInt(i) |
|
399 } else { |
|
400 return fmt.Errorf("cannot parse '%s' as int: %s", name, err) |
|
401 } |
|
402 case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": |
|
403 jn := data.(json.Number) |
|
404 i, err := jn.Int64() |
|
405 if err != nil { |
|
406 return fmt.Errorf( |
|
407 "error decoding json.Number into %s: %s", name, err) |
|
408 } |
|
409 val.SetInt(i) |
|
410 default: |
|
411 return fmt.Errorf( |
|
412 "'%s' expected type '%s', got unconvertible type '%s'", |
|
413 name, val.Type(), dataVal.Type()) |
|
414 } |
|
415 |
|
416 return nil |
|
417 } |
|
418 |
|
419 func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { |
|
420 dataVal := reflect.ValueOf(data) |
|
421 dataKind := getKind(dataVal) |
|
422 |
|
423 switch { |
|
424 case dataKind == reflect.Int: |
|
425 i := dataVal.Int() |
|
426 if i < 0 && !d.config.WeaklyTypedInput { |
|
427 return fmt.Errorf("cannot parse '%s', %d overflows uint", |
|
428 name, i) |
|
429 } |
|
430 val.SetUint(uint64(i)) |
|
431 case dataKind == reflect.Uint: |
|
432 val.SetUint(dataVal.Uint()) |
|
433 case dataKind == reflect.Float32: |
|
434 f := dataVal.Float() |
|
435 if f < 0 && !d.config.WeaklyTypedInput { |
|
436 return fmt.Errorf("cannot parse '%s', %f overflows uint", |
|
437 name, f) |
|
438 } |
|
439 val.SetUint(uint64(f)) |
|
440 case dataKind == reflect.Bool && d.config.WeaklyTypedInput: |
|
441 if dataVal.Bool() { |
|
442 val.SetUint(1) |
|
443 } else { |
|
444 val.SetUint(0) |
|
445 } |
|
446 case dataKind == reflect.String && d.config.WeaklyTypedInput: |
|
447 i, err := strconv.ParseUint(dataVal.String(), 0, val.Type().Bits()) |
|
448 if err == nil { |
|
449 val.SetUint(i) |
|
450 } else { |
|
451 return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) |
|
452 } |
|
453 default: |
|
454 return fmt.Errorf( |
|
455 "'%s' expected type '%s', got unconvertible type '%s'", |
|
456 name, val.Type(), dataVal.Type()) |
|
457 } |
|
458 |
|
459 return nil |
|
460 } |
|
461 |
|
462 func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { |
|
463 dataVal := reflect.ValueOf(data) |
|
464 dataKind := getKind(dataVal) |
|
465 |
|
466 switch { |
|
467 case dataKind == reflect.Bool: |
|
468 val.SetBool(dataVal.Bool()) |
|
469 case dataKind == reflect.Int && d.config.WeaklyTypedInput: |
|
470 val.SetBool(dataVal.Int() != 0) |
|
471 case dataKind == reflect.Uint && d.config.WeaklyTypedInput: |
|
472 val.SetBool(dataVal.Uint() != 0) |
|
473 case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: |
|
474 val.SetBool(dataVal.Float() != 0) |
|
475 case dataKind == reflect.String && d.config.WeaklyTypedInput: |
|
476 b, err := strconv.ParseBool(dataVal.String()) |
|
477 if err == nil { |
|
478 val.SetBool(b) |
|
479 } else if dataVal.String() == "" { |
|
480 val.SetBool(false) |
|
481 } else { |
|
482 return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) |
|
483 } |
|
484 default: |
|
485 return fmt.Errorf( |
|
486 "'%s' expected type '%s', got unconvertible type '%s'", |
|
487 name, val.Type(), dataVal.Type()) |
|
488 } |
|
489 |
|
490 return nil |
|
491 } |
|
492 |
|
493 func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { |
|
494 dataVal := reflect.ValueOf(data) |
|
495 dataKind := getKind(dataVal) |
|
496 dataType := dataVal.Type() |
|
497 |
|
498 switch { |
|
499 case dataKind == reflect.Int: |
|
500 val.SetFloat(float64(dataVal.Int())) |
|
501 case dataKind == reflect.Uint: |
|
502 val.SetFloat(float64(dataVal.Uint())) |
|
503 case dataKind == reflect.Float32: |
|
504 val.SetFloat(dataVal.Float()) |
|
505 case dataKind == reflect.Bool && d.config.WeaklyTypedInput: |
|
506 if dataVal.Bool() { |
|
507 val.SetFloat(1) |
|
508 } else { |
|
509 val.SetFloat(0) |
|
510 } |
|
511 case dataKind == reflect.String && d.config.WeaklyTypedInput: |
|
512 f, err := strconv.ParseFloat(dataVal.String(), val.Type().Bits()) |
|
513 if err == nil { |
|
514 val.SetFloat(f) |
|
515 } else { |
|
516 return fmt.Errorf("cannot parse '%s' as float: %s", name, err) |
|
517 } |
|
518 case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": |
|
519 jn := data.(json.Number) |
|
520 i, err := jn.Float64() |
|
521 if err != nil { |
|
522 return fmt.Errorf( |
|
523 "error decoding json.Number into %s: %s", name, err) |
|
524 } |
|
525 val.SetFloat(i) |
|
526 default: |
|
527 return fmt.Errorf( |
|
528 "'%s' expected type '%s', got unconvertible type '%s'", |
|
529 name, val.Type(), dataVal.Type()) |
|
530 } |
|
531 |
|
532 return nil |
|
533 } |
|
534 |
|
535 func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { |
|
536 valType := val.Type() |
|
537 valKeyType := valType.Key() |
|
538 valElemType := valType.Elem() |
|
539 |
|
540 // By default we overwrite keys in the current map |
|
541 valMap := val |
|
542 |
|
543 // If the map is nil or we're purposely zeroing fields, make a new map |
|
544 if valMap.IsNil() || d.config.ZeroFields { |
|
545 // Make a new map to hold our result |
|
546 mapType := reflect.MapOf(valKeyType, valElemType) |
|
547 valMap = reflect.MakeMap(mapType) |
|
548 } |
|
549 |
|
550 // Check input type and based on the input type jump to the proper func |
|
551 dataVal := reflect.Indirect(reflect.ValueOf(data)) |
|
552 switch dataVal.Kind() { |
|
553 case reflect.Map: |
|
554 return d.decodeMapFromMap(name, dataVal, val, valMap) |
|
555 |
|
556 case reflect.Struct: |
|
557 return d.decodeMapFromStruct(name, dataVal, val, valMap) |
|
558 |
|
559 case reflect.Array, reflect.Slice: |
|
560 if d.config.WeaklyTypedInput { |
|
561 return d.decodeMapFromSlice(name, dataVal, val, valMap) |
|
562 } |
|
563 |
|
564 fallthrough |
|
565 |
|
566 default: |
|
567 return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) |
|
568 } |
|
569 } |
|
570 |
|
571 func (d *Decoder) decodeMapFromSlice(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { |
|
572 // Special case for BC reasons (covered by tests) |
|
573 if dataVal.Len() == 0 { |
|
574 val.Set(valMap) |
|
575 return nil |
|
576 } |
|
577 |
|
578 for i := 0; i < dataVal.Len(); i++ { |
|
579 err := d.decode( |
|
580 fmt.Sprintf("%s[%d]", name, i), |
|
581 dataVal.Index(i).Interface(), val) |
|
582 if err != nil { |
|
583 return err |
|
584 } |
|
585 } |
|
586 |
|
587 return nil |
|
588 } |
|
589 |
|
590 func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { |
|
591 valType := val.Type() |
|
592 valKeyType := valType.Key() |
|
593 valElemType := valType.Elem() |
|
594 |
|
595 // Accumulate errors |
|
596 errors := make([]string, 0) |
|
597 |
|
598 for _, k := range dataVal.MapKeys() { |
|
599 fieldName := fmt.Sprintf("%s[%s]", name, k) |
|
600 |
|
601 // First decode the key into the proper type |
|
602 currentKey := reflect.Indirect(reflect.New(valKeyType)) |
|
603 if err := d.decode(fieldName, k.Interface(), currentKey); err != nil { |
|
604 errors = appendErrors(errors, err) |
|
605 continue |
|
606 } |
|
607 |
|
608 // Next decode the data into the proper type |
|
609 v := dataVal.MapIndex(k).Interface() |
|
610 currentVal := reflect.Indirect(reflect.New(valElemType)) |
|
611 if err := d.decode(fieldName, v, currentVal); err != nil { |
|
612 errors = appendErrors(errors, err) |
|
613 continue |
|
614 } |
|
615 |
|
616 valMap.SetMapIndex(currentKey, currentVal) |
|
617 } |
|
618 |
|
619 // Set the built up map to the value |
|
620 val.Set(valMap) |
|
621 |
|
622 // If we had errors, return those |
|
623 if len(errors) > 0 { |
|
624 return &Error{errors} |
|
625 } |
|
626 |
|
627 return nil |
|
628 } |
|
629 |
|
630 func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { |
|
631 typ := dataVal.Type() |
|
632 for i := 0; i < typ.NumField(); i++ { |
|
633 // Get the StructField first since this is a cheap operation. If the |
|
634 // field is unexported, then ignore it. |
|
635 f := typ.Field(i) |
|
636 if f.PkgPath != "" { |
|
637 continue |
|
638 } |
|
639 |
|
640 // Next get the actual value of this field and verify it is assignable |
|
641 // to the map value. |
|
642 v := dataVal.Field(i) |
|
643 if !v.Type().AssignableTo(valMap.Type().Elem()) { |
|
644 return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem()) |
|
645 } |
|
646 |
|
647 tagValue := f.Tag.Get(d.config.TagName) |
|
648 tagParts := strings.Split(tagValue, ",") |
|
649 |
|
650 // Determine the name of the key in the map |
|
651 keyName := f.Name |
|
652 if tagParts[0] != "" { |
|
653 if tagParts[0] == "-" { |
|
654 continue |
|
655 } |
|
656 keyName = tagParts[0] |
|
657 } |
|
658 |
|
659 // If "squash" is specified in the tag, we squash the field down. |
|
660 squash := false |
|
661 for _, tag := range tagParts[1:] { |
|
662 if tag == "squash" { |
|
663 squash = true |
|
664 break |
|
665 } |
|
666 } |
|
667 if squash && v.Kind() != reflect.Struct { |
|
668 return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) |
|
669 } |
|
670 |
|
671 switch v.Kind() { |
|
672 // this is an embedded struct, so handle it differently |
|
673 case reflect.Struct: |
|
674 x := reflect.New(v.Type()) |
|
675 x.Elem().Set(v) |
|
676 |
|
677 vType := valMap.Type() |
|
678 vKeyType := vType.Key() |
|
679 vElemType := vType.Elem() |
|
680 mType := reflect.MapOf(vKeyType, vElemType) |
|
681 vMap := reflect.MakeMap(mType) |
|
682 |
|
683 err := d.decode(keyName, x.Interface(), vMap) |
|
684 if err != nil { |
|
685 return err |
|
686 } |
|
687 |
|
688 if squash { |
|
689 for _, k := range vMap.MapKeys() { |
|
690 valMap.SetMapIndex(k, vMap.MapIndex(k)) |
|
691 } |
|
692 } else { |
|
693 valMap.SetMapIndex(reflect.ValueOf(keyName), vMap) |
|
694 } |
|
695 |
|
696 default: |
|
697 valMap.SetMapIndex(reflect.ValueOf(keyName), v) |
|
698 } |
|
699 } |
|
700 |
|
701 if val.CanAddr() { |
|
702 val.Set(valMap) |
|
703 } |
|
704 |
|
705 return nil |
|
706 } |
|
707 |
|
708 func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) error { |
|
709 // Create an element of the concrete (non pointer) type and decode |
|
710 // into that. Then set the value of the pointer to this type. |
|
711 valType := val.Type() |
|
712 valElemType := valType.Elem() |
|
713 |
|
714 if val.CanSet() { |
|
715 realVal := val |
|
716 if realVal.IsNil() || d.config.ZeroFields { |
|
717 realVal = reflect.New(valElemType) |
|
718 } |
|
719 |
|
720 if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { |
|
721 return err |
|
722 } |
|
723 |
|
724 val.Set(realVal) |
|
725 } else { |
|
726 if err := d.decode(name, data, reflect.Indirect(val)); err != nil { |
|
727 return err |
|
728 } |
|
729 } |
|
730 return nil |
|
731 } |
|
732 |
|
733 func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error { |
|
734 // Create an element of the concrete (non pointer) type and decode |
|
735 // into that. Then set the value of the pointer to this type. |
|
736 dataVal := reflect.Indirect(reflect.ValueOf(data)) |
|
737 if val.Type() != dataVal.Type() { |
|
738 return fmt.Errorf( |
|
739 "'%s' expected type '%s', got unconvertible type '%s'", |
|
740 name, val.Type(), dataVal.Type()) |
|
741 } |
|
742 val.Set(dataVal) |
|
743 return nil |
|
744 } |
|
745 |
|
746 func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { |
|
747 dataVal := reflect.Indirect(reflect.ValueOf(data)) |
|
748 dataValKind := dataVal.Kind() |
|
749 valType := val.Type() |
|
750 valElemType := valType.Elem() |
|
751 sliceType := reflect.SliceOf(valElemType) |
|
752 |
|
753 valSlice := val |
|
754 if valSlice.IsNil() || d.config.ZeroFields { |
|
755 // Check input type |
|
756 if dataValKind != reflect.Array && dataValKind != reflect.Slice { |
|
757 if d.config.WeaklyTypedInput { |
|
758 switch { |
|
759 // Empty maps turn into empty slices |
|
760 case dataValKind == reflect.Map: |
|
761 if dataVal.Len() == 0 { |
|
762 val.Set(reflect.MakeSlice(sliceType, 0, 0)) |
|
763 return nil |
|
764 } |
|
765 // Create slice of maps of other sizes |
|
766 return d.decodeSlice(name, []interface{}{data}, val) |
|
767 |
|
768 case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8: |
|
769 return d.decodeSlice(name, []byte(dataVal.String()), val) |
|
770 // All other types we try to convert to the slice type |
|
771 // and "lift" it into it. i.e. a string becomes a string slice. |
|
772 default: |
|
773 // Just re-try this function with data as a slice. |
|
774 return d.decodeSlice(name, []interface{}{data}, val) |
|
775 } |
|
776 } |
|
777 return fmt.Errorf( |
|
778 "'%s': source data must be an array or slice, got %s", name, dataValKind) |
|
779 |
|
780 } |
|
781 |
|
782 // Make a new slice to hold our result, same size as the original data. |
|
783 valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) |
|
784 } |
|
785 |
|
786 // Accumulate any errors |
|
787 errors := make([]string, 0) |
|
788 |
|
789 for i := 0; i < dataVal.Len(); i++ { |
|
790 currentData := dataVal.Index(i).Interface() |
|
791 for valSlice.Len() <= i { |
|
792 valSlice = reflect.Append(valSlice, reflect.Zero(valElemType)) |
|
793 } |
|
794 currentField := valSlice.Index(i) |
|
795 |
|
796 fieldName := fmt.Sprintf("%s[%d]", name, i) |
|
797 if err := d.decode(fieldName, currentData, currentField); err != nil { |
|
798 errors = appendErrors(errors, err) |
|
799 } |
|
800 } |
|
801 |
|
802 // Finally, set the value to the slice we built up |
|
803 val.Set(valSlice) |
|
804 |
|
805 // If there were errors, we return those |
|
806 if len(errors) > 0 { |
|
807 return &Error{errors} |
|
808 } |
|
809 |
|
810 return nil |
|
811 } |
|
812 |
|
813 func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error { |
|
814 dataVal := reflect.Indirect(reflect.ValueOf(data)) |
|
815 dataValKind := dataVal.Kind() |
|
816 valType := val.Type() |
|
817 valElemType := valType.Elem() |
|
818 arrayType := reflect.ArrayOf(valType.Len(), valElemType) |
|
819 |
|
820 valArray := val |
|
821 |
|
822 if valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields { |
|
823 // Check input type |
|
824 if dataValKind != reflect.Array && dataValKind != reflect.Slice { |
|
825 if d.config.WeaklyTypedInput { |
|
826 switch { |
|
827 // Empty maps turn into empty arrays |
|
828 case dataValKind == reflect.Map: |
|
829 if dataVal.Len() == 0 { |
|
830 val.Set(reflect.Zero(arrayType)) |
|
831 return nil |
|
832 } |
|
833 |
|
834 // All other types we try to convert to the array type |
|
835 // and "lift" it into it. i.e. a string becomes a string array. |
|
836 default: |
|
837 // Just re-try this function with data as a slice. |
|
838 return d.decodeArray(name, []interface{}{data}, val) |
|
839 } |
|
840 } |
|
841 |
|
842 return fmt.Errorf( |
|
843 "'%s': source data must be an array or slice, got %s", name, dataValKind) |
|
844 |
|
845 } |
|
846 if dataVal.Len() > arrayType.Len() { |
|
847 return fmt.Errorf( |
|
848 "'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len()) |
|
849 |
|
850 } |
|
851 |
|
852 // Make a new array to hold our result, same size as the original data. |
|
853 valArray = reflect.New(arrayType).Elem() |
|
854 } |
|
855 |
|
856 // Accumulate any errors |
|
857 errors := make([]string, 0) |
|
858 |
|
859 for i := 0; i < dataVal.Len(); i++ { |
|
860 currentData := dataVal.Index(i).Interface() |
|
861 currentField := valArray.Index(i) |
|
862 |
|
863 fieldName := fmt.Sprintf("%s[%d]", name, i) |
|
864 if err := d.decode(fieldName, currentData, currentField); err != nil { |
|
865 errors = appendErrors(errors, err) |
|
866 } |
|
867 } |
|
868 |
|
869 // Finally, set the value to the array we built up |
|
870 val.Set(valArray) |
|
871 |
|
872 // If there were errors, we return those |
|
873 if len(errors) > 0 { |
|
874 return &Error{errors} |
|
875 } |
|
876 |
|
877 return nil |
|
878 } |
|
879 |
|
880 func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { |
|
881 dataVal := reflect.Indirect(reflect.ValueOf(data)) |
|
882 |
|
883 // If the type of the value to write to and the data match directly, |
|
884 // then we just set it directly instead of recursing into the structure. |
|
885 if dataVal.Type() == val.Type() { |
|
886 val.Set(dataVal) |
|
887 return nil |
|
888 } |
|
889 |
|
890 dataValKind := dataVal.Kind() |
|
891 if dataValKind != reflect.Map { |
|
892 return fmt.Errorf("'%s' expected a map, got '%s'", name, dataValKind) |
|
893 } |
|
894 |
|
895 dataValType := dataVal.Type() |
|
896 if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { |
|
897 return fmt.Errorf( |
|
898 "'%s' needs a map with string keys, has '%s' keys", |
|
899 name, dataValType.Key().Kind()) |
|
900 } |
|
901 |
|
902 dataValKeys := make(map[reflect.Value]struct{}) |
|
903 dataValKeysUnused := make(map[interface{}]struct{}) |
|
904 for _, dataValKey := range dataVal.MapKeys() { |
|
905 dataValKeys[dataValKey] = struct{}{} |
|
906 dataValKeysUnused[dataValKey.Interface()] = struct{}{} |
|
907 } |
|
908 |
|
909 errors := make([]string, 0) |
|
910 |
|
911 // This slice will keep track of all the structs we'll be decoding. |
|
912 // There can be more than one struct if there are embedded structs |
|
913 // that are squashed. |
|
914 structs := make([]reflect.Value, 1, 5) |
|
915 structs[0] = val |
|
916 |
|
917 // Compile the list of all the fields that we're going to be decoding |
|
918 // from all the structs. |
|
919 type field struct { |
|
920 field reflect.StructField |
|
921 val reflect.Value |
|
922 } |
|
923 fields := []field{} |
|
924 for len(structs) > 0 { |
|
925 structVal := structs[0] |
|
926 structs = structs[1:] |
|
927 |
|
928 structType := structVal.Type() |
|
929 |
|
930 for i := 0; i < structType.NumField(); i++ { |
|
931 fieldType := structType.Field(i) |
|
932 fieldKind := fieldType.Type.Kind() |
|
933 |
|
934 // If "squash" is specified in the tag, we squash the field down. |
|
935 squash := false |
|
936 tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") |
|
937 for _, tag := range tagParts[1:] { |
|
938 if tag == "squash" { |
|
939 squash = true |
|
940 break |
|
941 } |
|
942 } |
|
943 |
|
944 if squash { |
|
945 if fieldKind != reflect.Struct { |
|
946 errors = appendErrors(errors, |
|
947 fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldKind)) |
|
948 } else { |
|
949 structs = append(structs, structVal.FieldByName(fieldType.Name)) |
|
950 } |
|
951 continue |
|
952 } |
|
953 |
|
954 // Normal struct field, store it away |
|
955 fields = append(fields, field{fieldType, structVal.Field(i)}) |
|
956 } |
|
957 } |
|
958 |
|
959 // for fieldType, field := range fields { |
|
960 for _, f := range fields { |
|
961 field, fieldValue := f.field, f.val |
|
962 fieldName := field.Name |
|
963 |
|
964 tagValue := field.Tag.Get(d.config.TagName) |
|
965 tagValue = strings.SplitN(tagValue, ",", 2)[0] |
|
966 if tagValue != "" { |
|
967 fieldName = tagValue |
|
968 } |
|
969 |
|
970 rawMapKey := reflect.ValueOf(fieldName) |
|
971 rawMapVal := dataVal.MapIndex(rawMapKey) |
|
972 if !rawMapVal.IsValid() { |
|
973 // Do a slower search by iterating over each key and |
|
974 // doing case-insensitive search. |
|
975 for dataValKey := range dataValKeys { |
|
976 mK, ok := dataValKey.Interface().(string) |
|
977 if !ok { |
|
978 // Not a string key |
|
979 continue |
|
980 } |
|
981 |
|
982 if strings.EqualFold(mK, fieldName) { |
|
983 rawMapKey = dataValKey |
|
984 rawMapVal = dataVal.MapIndex(dataValKey) |
|
985 break |
|
986 } |
|
987 } |
|
988 |
|
989 if !rawMapVal.IsValid() { |
|
990 // There was no matching key in the map for the value in |
|
991 // the struct. Just ignore. |
|
992 continue |
|
993 } |
|
994 } |
|
995 |
|
996 // Delete the key we're using from the unused map so we stop tracking |
|
997 delete(dataValKeysUnused, rawMapKey.Interface()) |
|
998 |
|
999 if !fieldValue.IsValid() { |
|
1000 // This should never happen |
|
1001 panic("field is not valid") |
|
1002 } |
|
1003 |
|
1004 // If we can't set the field, then it is unexported or something, |
|
1005 // and we just continue onwards. |
|
1006 if !fieldValue.CanSet() { |
|
1007 continue |
|
1008 } |
|
1009 |
|
1010 // If the name is empty string, then we're at the root, and we |
|
1011 // don't dot-join the fields. |
|
1012 if name != "" { |
|
1013 fieldName = fmt.Sprintf("%s.%s", name, fieldName) |
|
1014 } |
|
1015 |
|
1016 if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil { |
|
1017 errors = appendErrors(errors, err) |
|
1018 } |
|
1019 } |
|
1020 |
|
1021 if d.config.ErrorUnused && len(dataValKeysUnused) > 0 { |
|
1022 keys := make([]string, 0, len(dataValKeysUnused)) |
|
1023 for rawKey := range dataValKeysUnused { |
|
1024 keys = append(keys, rawKey.(string)) |
|
1025 } |
|
1026 sort.Strings(keys) |
|
1027 |
|
1028 err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) |
|
1029 errors = appendErrors(errors, err) |
|
1030 } |
|
1031 |
|
1032 if len(errors) > 0 { |
|
1033 return &Error{errors} |
|
1034 } |
|
1035 |
|
1036 // Add the unused keys to the list of unused keys if we're tracking metadata |
|
1037 if d.config.Metadata != nil { |
|
1038 for rawKey := range dataValKeysUnused { |
|
1039 key := rawKey.(string) |
|
1040 if name != "" { |
|
1041 key = fmt.Sprintf("%s.%s", name, key) |
|
1042 } |
|
1043 |
|
1044 d.config.Metadata.Unused = append(d.config.Metadata.Unused, key) |
|
1045 } |
|
1046 } |
|
1047 |
|
1048 return nil |
|
1049 } |
|
1050 |
|
1051 func getKind(val reflect.Value) reflect.Kind { |
|
1052 kind := val.Kind() |
|
1053 |
|
1054 switch { |
|
1055 case kind >= reflect.Int && kind <= reflect.Int64: |
|
1056 return reflect.Int |
|
1057 case kind >= reflect.Uint && kind <= reflect.Uint64: |
|
1058 return reflect.Uint |
|
1059 case kind >= reflect.Float32 && kind <= reflect.Float64: |
|
1060 return reflect.Float32 |
|
1061 default: |
|
1062 return kind |
|
1063 } |
|
1064 } |