1 // Package mapstructure exposes functionality to convert an arbitrary |
1 // Package mapstructure exposes functionality to convert one arbitrary |
2 // map[string]interface{} into a native Go structure. |
2 // Go type into another, typically to convert a map[string]interface{} |
|
3 // into a native Go structure. |
3 // |
4 // |
4 // The Go structure can be arbitrarily complex, containing slices, |
5 // The Go structure can be arbitrarily complex, containing slices, |
5 // other structs, etc. and the decoder will properly decode nested |
6 // 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 // 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 // See the examples to see what the decoder is capable of. |
|
9 // |
|
10 // The simplest function to start with is Decode. |
|
11 // |
|
12 // Field Tags |
|
13 // |
|
14 // When decoding to a struct, mapstructure will use the field name by |
|
15 // default to perform the mapping. For example, if a struct has a field |
|
16 // "Username" then mapstructure will look for a key in the source value |
|
17 // of "username" (case insensitive). |
|
18 // |
|
19 // type User struct { |
|
20 // Username string |
|
21 // } |
|
22 // |
|
23 // You can change the behavior of mapstructure by using struct tags. |
|
24 // The default struct tag that mapstructure looks for is "mapstructure" |
|
25 // but you can customize it using DecoderConfig. |
|
26 // |
|
27 // Renaming Fields |
|
28 // |
|
29 // To rename the key that mapstructure looks for, use the "mapstructure" |
|
30 // tag and set a value directly. For example, to change the "username" example |
|
31 // above to "user": |
|
32 // |
|
33 // type User struct { |
|
34 // Username string `mapstructure:"user"` |
|
35 // } |
|
36 // |
|
37 // Embedded Structs and Squashing |
|
38 // |
|
39 // Embedded structs are treated as if they're another field with that name. |
|
40 // By default, the two structs below are equivalent when decoding with |
|
41 // mapstructure: |
|
42 // |
|
43 // type Person struct { |
|
44 // Name string |
|
45 // } |
|
46 // |
|
47 // type Friend struct { |
|
48 // Person |
|
49 // } |
|
50 // |
|
51 // type Friend struct { |
|
52 // Person Person |
|
53 // } |
|
54 // |
|
55 // This would require an input that looks like below: |
|
56 // |
|
57 // map[string]interface{}{ |
|
58 // "person": map[string]interface{}{"name": "alice"}, |
|
59 // } |
|
60 // |
|
61 // If your "person" value is NOT nested, then you can append ",squash" to |
|
62 // your tag value and mapstructure will treat it as if the embedded struct |
|
63 // were part of the struct directly. Example: |
|
64 // |
|
65 // type Friend struct { |
|
66 // Person `mapstructure:",squash"` |
|
67 // } |
|
68 // |
|
69 // Now the following input would be accepted: |
|
70 // |
|
71 // map[string]interface{}{ |
|
72 // "name": "alice", |
|
73 // } |
|
74 // |
|
75 // When decoding from a struct to a map, the squash tag squashes the struct |
|
76 // fields into a single map. Using the example structs from above: |
|
77 // |
|
78 // Friend{Person: Person{Name: "alice"}} |
|
79 // |
|
80 // Will be decoded into a map: |
|
81 // |
|
82 // map[string]interface{}{ |
|
83 // "name": "alice", |
|
84 // } |
|
85 // |
|
86 // DecoderConfig has a field that changes the behavior of mapstructure |
|
87 // to always squash embedded structs. |
|
88 // |
|
89 // Remainder Values |
|
90 // |
|
91 // If there are any unmapped keys in the source value, mapstructure by |
|
92 // default will silently ignore them. You can error by setting ErrorUnused |
|
93 // in DecoderConfig. If you're using Metadata you can also maintain a slice |
|
94 // of the unused keys. |
|
95 // |
|
96 // You can also use the ",remain" suffix on your tag to collect all unused |
|
97 // values in a map. The field with this tag MUST be a map type and should |
|
98 // probably be a "map[string]interface{}" or "map[interface{}]interface{}". |
|
99 // See example below: |
|
100 // |
|
101 // type Friend struct { |
|
102 // Name string |
|
103 // Other map[string]interface{} `mapstructure:",remain"` |
|
104 // } |
|
105 // |
|
106 // Given the input below, Other would be populated with the other |
|
107 // values that weren't used (everything but "name"): |
|
108 // |
|
109 // map[string]interface{}{ |
|
110 // "name": "bob", |
|
111 // "address": "123 Maple St.", |
|
112 // } |
|
113 // |
|
114 // Omit Empty Values |
|
115 // |
|
116 // When decoding from a struct to any other value, you may use the |
|
117 // ",omitempty" suffix on your tag to omit that value if it equates to |
|
118 // the zero value. The zero value of all types is specified in the Go |
|
119 // specification. |
|
120 // |
|
121 // For example, the zero type of a numeric type is zero ("0"). If the struct |
|
122 // field value is zero and a numeric type, the field is empty, and it won't |
|
123 // be encoded into the destination type. |
|
124 // |
|
125 // type Source { |
|
126 // Age int `mapstructure:",omitempty"` |
|
127 // } |
|
128 // |
|
129 // Unexported fields |
|
130 // |
|
131 // Since unexported (private) struct fields cannot be set outside the package |
|
132 // where they are defined, the decoder will simply skip them. |
|
133 // |
|
134 // For this output type definition: |
|
135 // |
|
136 // type Exported struct { |
|
137 // private string // this unexported field will be skipped |
|
138 // Public string |
|
139 // } |
|
140 // |
|
141 // Using this map as input: |
|
142 // |
|
143 // map[string]interface{}{ |
|
144 // "private": "I will be ignored", |
|
145 // "Public": "I made it through!", |
|
146 // } |
|
147 // |
|
148 // The following struct will be decoded: |
|
149 // |
|
150 // type Exported struct { |
|
151 // private: "" // field is left with an empty string (zero value) |
|
152 // Public: "I made it through!" |
|
153 // } |
|
154 // |
|
155 // Other Configuration |
|
156 // |
|
157 // mapstructure is highly configurable. See the DecoderConfig struct |
|
158 // for other features and options that are supported. |
8 package mapstructure |
159 package mapstructure |
9 |
160 |
10 import ( |
161 import ( |
11 "encoding/json" |
162 "encoding/json" |
12 "errors" |
163 "errors" |
19 |
170 |
20 // DecodeHookFunc is the callback function that can be used for |
171 // DecodeHookFunc is the callback function that can be used for |
21 // data transformations. See "DecodeHook" in the DecoderConfig |
172 // data transformations. See "DecodeHook" in the DecoderConfig |
22 // struct. |
173 // struct. |
23 // |
174 // |
24 // The type should be DecodeHookFuncType or DecodeHookFuncKind. |
175 // The type must be one of DecodeHookFuncType, DecodeHookFuncKind, or |
25 // Either is accepted. Types are a superset of Kinds (Types can return |
176 // DecodeHookFuncValue. |
26 // Kinds) and are generally a richer thing to use, but Kinds are simpler |
177 // Values are a superset of Types (Values can return types), and Types are a |
27 // if you only need those. |
178 // superset of Kinds (Types can return Kinds) and are generally a richer thing |
|
179 // to use, but Kinds are simpler if you only need those. |
28 // |
180 // |
29 // The reason DecodeHookFunc is multi-typed is for backwards compatibility: |
181 // The reason DecodeHookFunc is multi-typed is for backwards compatibility: |
30 // we started with Kinds and then realized Types were the better solution, |
182 // 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 |
183 // but have a promise to not break backwards compat so we now support |
32 // both. |
184 // both. |
38 |
190 |
39 // DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the |
191 // DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the |
40 // source and target types. |
192 // source and target types. |
41 type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) |
193 type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) |
42 |
194 |
|
195 // DecodeHookFuncRaw is a DecodeHookFunc which has complete access to both the source and target |
|
196 // values. |
|
197 type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error) |
|
198 |
43 // DecoderConfig is the configuration that is used to create a new decoder |
199 // DecoderConfig is the configuration that is used to create a new decoder |
44 // and allows customization of various aspects of decoding. |
200 // and allows customization of various aspects of decoding. |
45 type DecoderConfig struct { |
201 type DecoderConfig struct { |
46 // DecodeHook, if set, will be called before any decoding and any |
202 // DecodeHook, if set, will be called before any decoding and any |
47 // type conversion (if WeaklyTypedInput is on). This lets you modify |
203 // type conversion (if WeaklyTypedInput is on). This lets you modify |
48 // the values before they're set down onto the resulting struct. |
204 // the values before they're set down onto the resulting struct. The |
|
205 // DecodeHook is called for every map and value in the input. This means |
|
206 // that if a struct has embedded fields with squash tags the decode hook |
|
207 // is called only once with all of the input data, not once for each |
|
208 // embedded struct. |
49 // |
209 // |
50 // If an error is returned, the entire decode will fail with that |
210 // If an error is returned, the entire decode will fail with that error. |
51 // error. |
|
52 DecodeHook DecodeHookFunc |
211 DecodeHook DecodeHookFunc |
53 |
212 |
54 // If ErrorUnused is true, then it is an error for there to exist |
213 // 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 |
214 // keys in the original map that were unused in the decoding process |
56 // (extra keys). |
215 // (extra keys). |
259 } |
426 } |
260 |
427 |
261 if d.config.DecodeHook != nil { |
428 if d.config.DecodeHook != nil { |
262 // We have a DecodeHook, so let's pre-process the input. |
429 // We have a DecodeHook, so let's pre-process the input. |
263 var err error |
430 var err error |
264 input, err = DecodeHookExec( |
431 input, err = DecodeHookExec(d.config.DecodeHook, inputVal, outVal) |
265 d.config.DecodeHook, |
|
266 inputVal.Type(), outVal.Type(), input) |
|
267 if err != nil { |
432 if err != nil { |
268 return fmt.Errorf("error decoding '%s': %s", name, err) |
433 return fmt.Errorf("error decoding '%s': %s", name, err) |
269 } |
434 } |
270 } |
435 } |
271 |
436 |
272 var err error |
437 var err error |
273 outputKind := getKind(outVal) |
438 outputKind := getKind(outVal) |
|
439 addMetaKey := true |
274 switch outputKind { |
440 switch outputKind { |
275 case reflect.Bool: |
441 case reflect.Bool: |
276 err = d.decodeBool(name, input, outVal) |
442 err = d.decodeBool(name, input, outVal) |
277 case reflect.Interface: |
443 case reflect.Interface: |
278 err = d.decodeBasic(name, input, outVal) |
444 err = d.decodeBasic(name, input, outVal) |
301 return fmt.Errorf("%s: unsupported type: %s", name, outputKind) |
467 return fmt.Errorf("%s: unsupported type: %s", name, outputKind) |
302 } |
468 } |
303 |
469 |
304 // If we reached here, then we successfully decoded SOMETHING, so |
470 // If we reached here, then we successfully decoded SOMETHING, so |
305 // mark the key as used if we're tracking metainput. |
471 // mark the key as used if we're tracking metainput. |
306 if d.config.Metadata != nil && name != "" { |
472 if addMetaKey && d.config.Metadata != nil && name != "" { |
307 d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) |
473 d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) |
308 } |
474 } |
309 |
475 |
310 return err |
476 return err |
311 } |
477 } |
312 |
478 |
313 // This decodes a basic type (bool, int, string, etc.) and sets the |
479 // This decodes a basic type (bool, int, string, etc.) and sets the |
314 // value to "data" of that type. |
480 // value to "data" of that type. |
315 func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { |
481 func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { |
316 if val.IsValid() && val.Elem().IsValid() { |
482 if val.IsValid() && val.Elem().IsValid() { |
317 return d.decode(name, data, val.Elem()) |
483 elem := val.Elem() |
|
484 |
|
485 // If we can't address this element, then its not writable. Instead, |
|
486 // we make a copy of the value (which is a pointer and therefore |
|
487 // writable), decode into that, and replace the whole value. |
|
488 copied := false |
|
489 if !elem.CanAddr() { |
|
490 copied = true |
|
491 |
|
492 // Make *T |
|
493 copy := reflect.New(elem.Type()) |
|
494 |
|
495 // *T = elem |
|
496 copy.Elem().Set(elem) |
|
497 |
|
498 // Set elem so we decode into it |
|
499 elem = copy |
|
500 } |
|
501 |
|
502 // Decode. If we have an error then return. We also return right |
|
503 // away if we're not a copy because that means we decoded directly. |
|
504 if err := d.decode(name, data, elem); err != nil || !copied { |
|
505 return err |
|
506 } |
|
507 |
|
508 // If we're a copy, we need to set te final result |
|
509 val.Set(elem.Elem()) |
|
510 return nil |
318 } |
511 } |
319 |
512 |
320 dataVal := reflect.ValueOf(data) |
513 dataVal := reflect.ValueOf(data) |
321 |
514 |
322 // If the input data is a pointer, and the assigned type is the dereference |
515 // If the input data is a pointer, and the assigned type is the dereference |
426 "error decoding json.Number into %s: %s", name, err) |
624 "error decoding json.Number into %s: %s", name, err) |
427 } |
625 } |
428 val.SetInt(i) |
626 val.SetInt(i) |
429 default: |
627 default: |
430 return fmt.Errorf( |
628 return fmt.Errorf( |
431 "'%s' expected type '%s', got unconvertible type '%s'", |
629 "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", |
432 name, val.Type(), dataVal.Type()) |
630 name, val.Type(), dataVal.Type(), data) |
433 } |
631 } |
434 |
632 |
435 return nil |
633 return nil |
436 } |
634 } |
437 |
635 |
438 func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { |
636 func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { |
439 dataVal := reflect.Indirect(reflect.ValueOf(data)) |
637 dataVal := reflect.Indirect(reflect.ValueOf(data)) |
440 dataKind := getKind(dataVal) |
638 dataKind := getKind(dataVal) |
|
639 dataType := dataVal.Type() |
441 |
640 |
442 switch { |
641 switch { |
443 case dataKind == reflect.Int: |
642 case dataKind == reflect.Int: |
444 i := dataVal.Int() |
643 i := dataVal.Int() |
445 if i < 0 && !d.config.WeaklyTypedInput { |
644 if i < 0 && !d.config.WeaklyTypedInput { |
461 val.SetUint(1) |
660 val.SetUint(1) |
462 } else { |
661 } else { |
463 val.SetUint(0) |
662 val.SetUint(0) |
464 } |
663 } |
465 case dataKind == reflect.String && d.config.WeaklyTypedInput: |
664 case dataKind == reflect.String && d.config.WeaklyTypedInput: |
466 i, err := strconv.ParseUint(dataVal.String(), 0, val.Type().Bits()) |
665 str := dataVal.String() |
|
666 if str == "" { |
|
667 str = "0" |
|
668 } |
|
669 |
|
670 i, err := strconv.ParseUint(str, 0, val.Type().Bits()) |
467 if err == nil { |
671 if err == nil { |
468 val.SetUint(i) |
672 val.SetUint(i) |
469 } else { |
673 } else { |
470 return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) |
674 return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) |
471 } |
675 } |
|
676 case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": |
|
677 jn := data.(json.Number) |
|
678 i, err := jn.Int64() |
|
679 if err != nil { |
|
680 return fmt.Errorf( |
|
681 "error decoding json.Number into %s: %s", name, err) |
|
682 } |
|
683 if i < 0 && !d.config.WeaklyTypedInput { |
|
684 return fmt.Errorf("cannot parse '%s', %d overflows uint", |
|
685 name, i) |
|
686 } |
|
687 val.SetUint(uint64(i)) |
472 default: |
688 default: |
473 return fmt.Errorf( |
689 return fmt.Errorf( |
474 "'%s' expected type '%s', got unconvertible type '%s'", |
690 "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", |
475 name, val.Type(), dataVal.Type()) |
691 name, val.Type(), dataVal.Type(), data) |
476 } |
692 } |
477 |
693 |
478 return nil |
694 return nil |
479 } |
695 } |
480 |
696 |
676 if !v.Type().AssignableTo(valMap.Type().Elem()) { |
897 if !v.Type().AssignableTo(valMap.Type().Elem()) { |
677 return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem()) |
898 return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem()) |
678 } |
899 } |
679 |
900 |
680 tagValue := f.Tag.Get(d.config.TagName) |
901 tagValue := f.Tag.Get(d.config.TagName) |
681 tagParts := strings.Split(tagValue, ",") |
902 keyName := f.Name |
|
903 |
|
904 // If Squash is set in the config, we squash the field down. |
|
905 squash := d.config.Squash && v.Kind() == reflect.Struct && f.Anonymous |
682 |
906 |
683 // Determine the name of the key in the map |
907 // Determine the name of the key in the map |
684 keyName := f.Name |
908 if index := strings.Index(tagValue, ","); index != -1 { |
685 if tagParts[0] != "" { |
909 if tagValue[:index] == "-" { |
686 if tagParts[0] == "-" { |
|
687 continue |
910 continue |
688 } |
911 } |
689 keyName = tagParts[0] |
912 // If "omitempty" is specified in the tag, it ignores empty values. |
690 } |
913 if strings.Index(tagValue[index+1:], "omitempty") != -1 && isEmptyValue(v) { |
691 |
914 continue |
692 // If "squash" is specified in the tag, we squash the field down. |
915 } |
693 squash := false |
916 |
694 for _, tag := range tagParts[1:] { |
917 // If "squash" is specified in the tag, we squash the field down. |
695 if tag == "squash" { |
918 squash = !squash && strings.Index(tagValue[index+1:], "squash") != -1 |
696 squash = true |
919 if squash { |
697 break |
920 // When squashing, the embedded type can be a pointer to a struct. |
698 } |
921 if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { |
699 } |
922 v = v.Elem() |
700 if squash && v.Kind() != reflect.Struct { |
923 } |
701 return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) |
924 |
|
925 // The final type must be a struct |
|
926 if v.Kind() != reflect.Struct { |
|
927 return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) |
|
928 } |
|
929 } |
|
930 keyName = tagValue[:index] |
|
931 } else if len(tagValue) > 0 { |
|
932 if tagValue == "-" { |
|
933 continue |
|
934 } |
|
935 keyName = tagValue |
702 } |
936 } |
703 |
937 |
704 switch v.Kind() { |
938 switch v.Kind() { |
705 // this is an embedded struct, so handle it differently |
939 // this is an embedded struct, so handle it differently |
706 case reflect.Struct: |
940 case reflect.Struct: |
711 vKeyType := vType.Key() |
945 vKeyType := vType.Key() |
712 vElemType := vType.Elem() |
946 vElemType := vType.Elem() |
713 mType := reflect.MapOf(vKeyType, vElemType) |
947 mType := reflect.MapOf(vKeyType, vElemType) |
714 vMap := reflect.MakeMap(mType) |
948 vMap := reflect.MakeMap(mType) |
715 |
949 |
716 err := d.decode(keyName, x.Interface(), vMap) |
950 // Creating a pointer to a map so that other methods can completely |
|
951 // overwrite the map if need be (looking at you decodeMapFromMap). The |
|
952 // indirection allows the underlying map to be settable (CanSet() == true) |
|
953 // where as reflect.MakeMap returns an unsettable map. |
|
954 addrVal := reflect.New(vMap.Type()) |
|
955 reflect.Indirect(addrVal).Set(vMap) |
|
956 |
|
957 err := d.decode(keyName, x.Interface(), reflect.Indirect(addrVal)) |
717 if err != nil { |
958 if err != nil { |
718 return err |
959 return err |
719 } |
960 } |
|
961 |
|
962 // the underlying map may have been completely overwritten so pull |
|
963 // it indirectly out of the enclosing value. |
|
964 vMap = reflect.Indirect(addrVal) |
720 |
965 |
721 if squash { |
966 if squash { |
722 for _, k := range vMap.MapKeys() { |
967 for _, k := range vMap.MapKeys() { |
723 valMap.SetMapIndex(k, vMap.MapIndex(k)) |
968 valMap.SetMapIndex(k, vMap.MapIndex(k)) |
724 } |
969 } |
771 if realVal.IsNil() || d.config.ZeroFields { |
1016 if realVal.IsNil() || d.config.ZeroFields { |
772 realVal = reflect.New(valElemType) |
1017 realVal = reflect.New(valElemType) |
773 } |
1018 } |
774 |
1019 |
775 if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { |
1020 if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { |
776 return err |
1021 return false, err |
777 } |
1022 } |
778 |
1023 |
779 val.Set(realVal) |
1024 val.Set(realVal) |
780 } else { |
1025 } else { |
781 if err := d.decode(name, data, reflect.Indirect(val)); err != nil { |
1026 if err := d.decode(name, data, reflect.Indirect(val)); err != nil { |
782 return err |
1027 return false, err |
783 } |
1028 } |
784 } |
1029 } |
785 return nil |
1030 return false, nil |
786 } |
1031 } |
787 |
1032 |
788 func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error { |
1033 func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error { |
789 // Create an element of the concrete (non pointer) type and decode |
1034 // Create an element of the concrete (non pointer) type and decode |
790 // into that. Then set the value of the pointer to this type. |
1035 // into that. Then set the value of the pointer to this type. |
791 dataVal := reflect.Indirect(reflect.ValueOf(data)) |
1036 dataVal := reflect.Indirect(reflect.ValueOf(data)) |
792 if val.Type() != dataVal.Type() { |
1037 if val.Type() != dataVal.Type() { |
793 return fmt.Errorf( |
1038 return fmt.Errorf( |
794 "'%s' expected type '%s', got unconvertible type '%s'", |
1039 "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", |
795 name, val.Type(), dataVal.Type()) |
1040 name, val.Type(), dataVal.Type(), data) |
796 } |
1041 } |
797 val.Set(dataVal) |
1042 val.Set(dataVal) |
798 return nil |
1043 return nil |
799 } |
1044 } |
800 |
1045 |
831 // Just re-try this function with data as a slice. |
1076 // Just re-try this function with data as a slice. |
832 return d.decodeSlice(name, []interface{}{data}, val) |
1077 return d.decodeSlice(name, []interface{}{data}, val) |
833 } |
1078 } |
834 } |
1079 } |
835 |
1080 |
836 // Check input type |
1081 return fmt.Errorf( |
837 if dataValKind != reflect.Array && dataValKind != reflect.Slice { |
1082 "'%s': source data must be an array or slice, got %s", name, dataValKind) |
838 return fmt.Errorf( |
1083 } |
839 "'%s': source data must be an array or slice, got %s", name, dataValKind) |
1084 |
840 |
1085 // If the input value is nil, then don't allocate since empty != nil |
841 } |
1086 if dataVal.IsNil() { |
842 |
1087 return nil |
843 // If the input value is empty, then don't allocate since non-nil != nil |
1088 } |
844 if dataVal.Len() == 0 { |
1089 |
845 return nil |
1090 valSlice := val |
846 } |
1091 if valSlice.IsNil() || d.config.ZeroFields { |
847 |
|
848 // Make a new slice to hold our result, same size as the original data. |
1092 // Make a new slice to hold our result, same size as the original data. |
849 valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) |
1093 valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) |
850 } |
1094 } |
851 |
1095 |
852 // Accumulate any errors |
1096 // Accumulate any errors |
960 |
1204 |
961 case reflect.Struct: |
1205 case reflect.Struct: |
962 // Not the most efficient way to do this but we can optimize later if |
1206 // Not the most efficient way to do this but we can optimize later if |
963 // we want to. To convert from struct to struct we go to map first |
1207 // we want to. To convert from struct to struct we go to map first |
964 // as an intermediary. |
1208 // as an intermediary. |
965 m := make(map[string]interface{}) |
1209 |
966 mval := reflect.Indirect(reflect.ValueOf(&m)) |
1210 // Make a new map to hold our result |
967 if err := d.decodeMapFromStruct(name, dataVal, mval, mval); err != nil { |
1211 mapType := reflect.TypeOf((map[string]interface{})(nil)) |
|
1212 mval := reflect.MakeMap(mapType) |
|
1213 |
|
1214 // Creating a pointer to a map so that other methods can completely |
|
1215 // overwrite the map if need be (looking at you decodeMapFromMap). The |
|
1216 // indirection allows the underlying map to be settable (CanSet() == true) |
|
1217 // where as reflect.MakeMap returns an unsettable map. |
|
1218 addrVal := reflect.New(mval.Type()) |
|
1219 |
|
1220 reflect.Indirect(addrVal).Set(mval) |
|
1221 if err := d.decodeMapFromStruct(name, dataVal, reflect.Indirect(addrVal), mval); err != nil { |
968 return err |
1222 return err |
969 } |
1223 } |
970 |
1224 |
971 result := d.decodeStructFromMap(name, mval, val) |
1225 result := d.decodeStructFromMap(name, reflect.Indirect(addrVal), val) |
972 return result |
1226 return result |
973 |
1227 |
974 default: |
1228 default: |
975 return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) |
1229 return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) |
976 } |
1230 } |
1003 // from all the structs. |
1257 // from all the structs. |
1004 type field struct { |
1258 type field struct { |
1005 field reflect.StructField |
1259 field reflect.StructField |
1006 val reflect.Value |
1260 val reflect.Value |
1007 } |
1261 } |
|
1262 |
|
1263 // remainField is set to a valid field set with the "remain" tag if |
|
1264 // we are keeping track of remaining values. |
|
1265 var remainField *field |
|
1266 |
1008 fields := []field{} |
1267 fields := []field{} |
1009 for len(structs) > 0 { |
1268 for len(structs) > 0 { |
1010 structVal := structs[0] |
1269 structVal := structs[0] |
1011 structs = structs[1:] |
1270 structs = structs[1:] |
1012 |
1271 |
1013 structType := structVal.Type() |
1272 structType := structVal.Type() |
1014 |
1273 |
1015 for i := 0; i < structType.NumField(); i++ { |
1274 for i := 0; i < structType.NumField(); i++ { |
1016 fieldType := structType.Field(i) |
1275 fieldType := structType.Field(i) |
1017 fieldKind := fieldType.Type.Kind() |
1276 fieldVal := structVal.Field(i) |
|
1277 if fieldVal.Kind() == reflect.Ptr && fieldVal.Elem().Kind() == reflect.Struct { |
|
1278 // Handle embedded struct pointers as embedded structs. |
|
1279 fieldVal = fieldVal.Elem() |
|
1280 } |
1018 |
1281 |
1019 // If "squash" is specified in the tag, we squash the field down. |
1282 // If "squash" is specified in the tag, we squash the field down. |
1020 squash := false |
1283 squash := d.config.Squash && fieldVal.Kind() == reflect.Struct && fieldType.Anonymous |
|
1284 remain := false |
|
1285 |
|
1286 // We always parse the tags cause we're looking for other tags too |
1021 tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") |
1287 tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") |
1022 for _, tag := range tagParts[1:] { |
1288 for _, tag := range tagParts[1:] { |
1023 if tag == "squash" { |
1289 if tag == "squash" { |
1024 squash = true |
1290 squash = true |
1025 break |
1291 break |
1026 } |
1292 } |
|
1293 |
|
1294 if tag == "remain" { |
|
1295 remain = true |
|
1296 break |
|
1297 } |
1027 } |
1298 } |
1028 |
1299 |
1029 if squash { |
1300 if squash { |
1030 if fieldKind != reflect.Struct { |
1301 if fieldVal.Kind() != reflect.Struct { |
1031 errors = appendErrors(errors, |
1302 errors = appendErrors(errors, |
1032 fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldKind)) |
1303 fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind())) |
1033 } else { |
1304 } else { |
1034 structs = append(structs, structVal.FieldByName(fieldType.Name)) |
1305 structs = append(structs, fieldVal) |
1035 } |
1306 } |
1036 continue |
1307 continue |
1037 } |
1308 } |
1038 |
1309 |
1039 // Normal struct field, store it away |
1310 // Build our field |
1040 fields = append(fields, field{fieldType, structVal.Field(i)}) |
1311 if remain { |
|
1312 remainField = &field{fieldType, fieldVal} |
|
1313 } else { |
|
1314 // Normal struct field, store it away |
|
1315 fields = append(fields, field{fieldType, fieldVal}) |
|
1316 } |
1041 } |
1317 } |
1042 } |
1318 } |
1043 |
1319 |
1044 // for fieldType, field := range fields { |
1320 // for fieldType, field := range fields { |
1045 for _, f := range fields { |
1321 for _, f := range fields { |
1090 // and we just continue onwards. |
1363 // and we just continue onwards. |
1091 if !fieldValue.CanSet() { |
1364 if !fieldValue.CanSet() { |
1092 continue |
1365 continue |
1093 } |
1366 } |
1094 |
1367 |
|
1368 // Delete the key we're using from the unused map so we stop tracking |
|
1369 delete(dataValKeysUnused, rawMapKey.Interface()) |
|
1370 |
1095 // If the name is empty string, then we're at the root, and we |
1371 // If the name is empty string, then we're at the root, and we |
1096 // don't dot-join the fields. |
1372 // don't dot-join the fields. |
1097 if name != "" { |
1373 if name != "" { |
1098 fieldName = fmt.Sprintf("%s.%s", name, fieldName) |
1374 fieldName = name + "." + fieldName |
1099 } |
1375 } |
1100 |
1376 |
1101 if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil { |
1377 if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil { |
1102 errors = appendErrors(errors, err) |
1378 errors = appendErrors(errors, err) |
1103 } |
1379 } |
|
1380 } |
|
1381 |
|
1382 // If we have a "remain"-tagged field and we have unused keys then |
|
1383 // we put the unused keys directly into the remain field. |
|
1384 if remainField != nil && len(dataValKeysUnused) > 0 { |
|
1385 // Build a map of only the unused values |
|
1386 remain := map[interface{}]interface{}{} |
|
1387 for key := range dataValKeysUnused { |
|
1388 remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface() |
|
1389 } |
|
1390 |
|
1391 // Decode it as-if we were just decoding this map onto our map. |
|
1392 if err := d.decodeMap(name, remain, remainField.val); err != nil { |
|
1393 errors = appendErrors(errors, err) |
|
1394 } |
|
1395 |
|
1396 // Set the map to nil so we have none so that the next check will |
|
1397 // not error (ErrorUnused) |
|
1398 dataValKeysUnused = nil |
1104 } |
1399 } |
1105 |
1400 |
1106 if d.config.ErrorUnused && len(dataValKeysUnused) > 0 { |
1401 if d.config.ErrorUnused && len(dataValKeysUnused) > 0 { |
1107 keys := make([]string, 0, len(dataValKeysUnused)) |
1402 keys := make([]string, 0, len(dataValKeysUnused)) |
1108 for rawKey := range dataValKeysUnused { |
1403 for rawKey := range dataValKeysUnused { |
1121 // Add the unused keys to the list of unused keys if we're tracking metadata |
1416 // Add the unused keys to the list of unused keys if we're tracking metadata |
1122 if d.config.Metadata != nil { |
1417 if d.config.Metadata != nil { |
1123 for rawKey := range dataValKeysUnused { |
1418 for rawKey := range dataValKeysUnused { |
1124 key := rawKey.(string) |
1419 key := rawKey.(string) |
1125 if name != "" { |
1420 if name != "" { |
1126 key = fmt.Sprintf("%s.%s", name, key) |
1421 key = name + "." + key |
1127 } |
1422 } |
1128 |
1423 |
1129 d.config.Metadata.Unused = append(d.config.Metadata.Unused, key) |
1424 d.config.Metadata.Unused = append(d.config.Metadata.Unused, key) |
1130 } |
1425 } |
1131 } |
1426 } |
1132 |
1427 |
1133 return nil |
1428 return nil |
|
1429 } |
|
1430 |
|
1431 func isEmptyValue(v reflect.Value) bool { |
|
1432 switch getKind(v) { |
|
1433 case reflect.Array, reflect.Map, reflect.Slice, reflect.String: |
|
1434 return v.Len() == 0 |
|
1435 case reflect.Bool: |
|
1436 return !v.Bool() |
|
1437 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: |
|
1438 return v.Int() == 0 |
|
1439 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: |
|
1440 return v.Uint() == 0 |
|
1441 case reflect.Float32, reflect.Float64: |
|
1442 return v.Float() == 0 |
|
1443 case reflect.Interface, reflect.Ptr: |
|
1444 return v.IsNil() |
|
1445 } |
|
1446 return false |
1134 } |
1447 } |
1135 |
1448 |
1136 func getKind(val reflect.Value) reflect.Kind { |
1449 func getKind(val reflect.Value) reflect.Kind { |
1137 kind := val.Kind() |
1450 kind := val.Kind() |
1138 |
1451 |