|
9 | 9 | // |
10 | 10 | // The simplest function to start with is Decode. |
11 | 11 | // |
12 | | -// Field Tags |
| 12 | +// # Field Tags |
13 | 13 | // |
14 | 14 | // When decoding to a struct, mapstructure will use the field name by |
15 | 15 | // default to perform the mapping. For example, if a struct has a field |
16 | 16 | // "Username" then mapstructure will look for a key in the source value |
17 | 17 | // of "username" (case insensitive). |
18 | 18 | // |
19 | | -// type User struct { |
20 | | -// Username string |
21 | | -// } |
| 19 | +// type User struct { |
| 20 | +// Username string |
| 21 | +// } |
22 | 22 | // |
23 | 23 | // You can change the behavior of mapstructure by using struct tags. |
24 | 24 | // The default struct tag that mapstructure looks for is "mapstructure" |
25 | 25 | // but you can customize it using DecoderConfig. |
26 | 26 | // |
27 | | -// Renaming Fields |
| 27 | +// # Renaming Fields |
28 | 28 | // |
29 | 29 | // To rename the key that mapstructure looks for, use the "mapstructure" |
30 | 30 | // tag and set a value directly. For example, to change the "username" example |
31 | 31 | // above to "user": |
32 | 32 | // |
33 | | -// type User struct { |
34 | | -// Username string `mapstructure:"user"` |
35 | | -// } |
| 33 | +// type User struct { |
| 34 | +// Username string `mapstructure:"user"` |
| 35 | +// } |
36 | 36 | // |
37 | | -// Embedded Structs and Squashing |
| 37 | +// # Embedded Structs and Squashing |
38 | 38 | // |
39 | 39 | // Embedded structs are treated as if they're another field with that name. |
40 | 40 | // By default, the two structs below are equivalent when decoding with |
41 | 41 | // mapstructure: |
42 | 42 | // |
43 | | -// type Person struct { |
44 | | -// Name string |
45 | | -// } |
| 43 | +// type Person struct { |
| 44 | +// Name string |
| 45 | +// } |
46 | 46 | // |
47 | | -// type Friend struct { |
48 | | -// Person |
49 | | -// } |
| 47 | +// type Friend struct { |
| 48 | +// Person |
| 49 | +// } |
50 | 50 | // |
51 | | -// type Friend struct { |
52 | | -// Person Person |
53 | | -// } |
| 51 | +// type Friend struct { |
| 52 | +// Person Person |
| 53 | +// } |
54 | 54 | // |
55 | 55 | // This would require an input that looks like below: |
56 | 56 | // |
57 | | -// map[string]interface{}{ |
58 | | -// "person": map[string]interface{}{"name": "alice"}, |
59 | | -// } |
| 57 | +// map[string]interface{}{ |
| 58 | +// "person": map[string]interface{}{"name": "alice"}, |
| 59 | +// } |
60 | 60 | // |
61 | 61 | // If your "person" value is NOT nested, then you can append ",squash" to |
62 | 62 | // your tag value and mapstructure will treat it as if the embedded struct |
63 | 63 | // were part of the struct directly. Example: |
64 | 64 | // |
65 | | -// type Friend struct { |
66 | | -// Person `mapstructure:",squash"` |
67 | | -// } |
| 65 | +// type Friend struct { |
| 66 | +// Person `mapstructure:",squash"` |
| 67 | +// } |
68 | 68 | // |
69 | 69 | // Now the following input would be accepted: |
70 | 70 | // |
71 | | -// map[string]interface{}{ |
72 | | -// "name": "alice", |
73 | | -// } |
| 71 | +// map[string]interface{}{ |
| 72 | +// "name": "alice", |
| 73 | +// } |
74 | 74 | // |
75 | 75 | // When decoding from a struct to a map, the squash tag squashes the struct |
76 | 76 | // fields into a single map. Using the example structs from above: |
77 | 77 | // |
78 | | -// Friend{Person: Person{Name: "alice"}} |
| 78 | +// Friend{Person: Person{Name: "alice"}} |
79 | 79 | // |
80 | 80 | // Will be decoded into a map: |
81 | 81 | // |
82 | | -// map[string]interface{}{ |
83 | | -// "name": "alice", |
84 | | -// } |
| 82 | +// map[string]interface{}{ |
| 83 | +// "name": "alice", |
| 84 | +// } |
85 | 85 | // |
86 | 86 | // DecoderConfig has a field that changes the behavior of mapstructure |
87 | 87 | // to always squash embedded structs. |
88 | 88 | // |
89 | | -// Remainder Values |
| 89 | +// # Remainder Values |
90 | 90 | // |
91 | 91 | // If there are any unmapped keys in the source value, mapstructure by |
92 | 92 | // default will silently ignore them. You can error by setting ErrorUnused |
|
98 | 98 | // probably be a "map[string]interface{}" or "map[interface{}]interface{}". |
99 | 99 | // See example below: |
100 | 100 | // |
101 | | -// type Friend struct { |
102 | | -// Name string |
103 | | -// Other map[string]interface{} `mapstructure:",remain"` |
104 | | -// } |
| 101 | +// type Friend struct { |
| 102 | +// Name string |
| 103 | +// Other map[string]interface{} `mapstructure:",remain"` |
| 104 | +// } |
105 | 105 | // |
106 | 106 | // Given the input below, Other would be populated with the other |
107 | 107 | // values that weren't used (everything but "name"): |
108 | 108 | // |
109 | | -// map[string]interface{}{ |
110 | | -// "name": "bob", |
111 | | -// "address": "123 Maple St.", |
112 | | -// } |
| 109 | +// map[string]interface{}{ |
| 110 | +// "name": "bob", |
| 111 | +// "address": "123 Maple St.", |
| 112 | +// } |
113 | 113 | // |
114 | | -// Omit Empty Values |
| 114 | +// # Omit Empty Values |
115 | 115 | // |
116 | 116 | // When decoding from a struct to any other value, you may use the |
117 | 117 | // ",omitempty" suffix on your tag to omit that value if it equates to |
|
122 | 122 | // field value is zero and a numeric type, the field is empty, and it won't |
123 | 123 | // be encoded into the destination type. |
124 | 124 | // |
125 | | -// type Source struct { |
126 | | -// Age int `mapstructure:",omitempty"` |
127 | | -// } |
| 125 | +// type Source struct { |
| 126 | +// Age int `mapstructure:",omitempty"` |
| 127 | +// } |
128 | 128 | // |
129 | | -// Unexported fields |
| 129 | +// # Unexported fields |
130 | 130 | // |
131 | 131 | // Since unexported (private) struct fields cannot be set outside the package |
132 | 132 | // where they are defined, the decoder will simply skip them. |
133 | 133 | // |
134 | 134 | // For this output type definition: |
135 | 135 | // |
136 | | -// type Exported struct { |
137 | | -// private string // this unexported field will be skipped |
138 | | -// Public string |
139 | | -// } |
| 136 | +// type Exported struct { |
| 137 | +// private string // this unexported field will be skipped |
| 138 | +// Public string |
| 139 | +// } |
140 | 140 | // |
141 | 141 | // Using this map as input: |
142 | 142 | // |
143 | | -// map[string]interface{}{ |
144 | | -// "private": "I will be ignored", |
145 | | -// "Public": "I made it through!", |
146 | | -// } |
| 143 | +// map[string]interface{}{ |
| 144 | +// "private": "I will be ignored", |
| 145 | +// "Public": "I made it through!", |
| 146 | +// } |
147 | 147 | // |
148 | 148 | // The following struct will be decoded: |
149 | 149 | // |
150 | | -// type Exported struct { |
151 | | -// private: "" // field is left with an empty string (zero value) |
152 | | -// Public: "I made it through!" |
153 | | -// } |
| 150 | +// type Exported struct { |
| 151 | +// private: "" // field is left with an empty string (zero value) |
| 152 | +// Public: "I made it through!" |
| 153 | +// } |
154 | 154 | // |
155 | | -// Other Configuration |
| 155 | +// # Other Configuration |
156 | 156 | // |
157 | 157 | // mapstructure is highly configurable. See the DecoderConfig struct |
158 | 158 | // for other features and options that are supported. |
@@ -1358,8 +1358,8 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e |
1358 | 1358 | fieldName := field.Name |
1359 | 1359 |
|
1360 | 1360 | tagValue := field.Tag.Get(d.config.TagName) |
1361 | | - tagValue = strings.SplitN(tagValue, ",", 2)[0] |
1362 | 1361 | if tagValue != "" { |
| 1362 | + tagValue, _, _ = strings.Cut(tagValue, ",") |
1363 | 1363 | fieldName = tagValue |
1364 | 1364 | } |
1365 | 1365 |
|
|
0 commit comments