1package mapstructure
2
3import (
4	"fmt"
5)
6
7func ExampleDecode() {
8	type Person struct {
9		Name   string
10		Age    int
11		Emails []string
12		Extra  map[string]string
13	}
14
15	// This input can come from anywhere, but typically comes from
16	// something like decoding JSON where we're not quite sure of the
17	// struct initially.
18	input := map[string]interface{}{
19		"name":   "Mitchell",
20		"age":    91,
21		"emails": []string{"one", "two", "three"},
22		"extra": map[string]string{
23			"twitter": "mitchellh",
24		},
25	}
26
27	var result Person
28	err := Decode(input, &result)
29	if err != nil {
30		panic(err)
31	}
32
33	fmt.Printf("%#v", result)
34	// Output:
35	// mapstructure.Person{Name:"Mitchell", Age:91, Emails:[]string{"one", "two", "three"}, Extra:map[string]string{"twitter":"mitchellh"}}
36}
37
38func ExampleDecode_errors() {
39	type Person struct {
40		Name   string
41		Age    int
42		Emails []string
43		Extra  map[string]string
44	}
45
46	// This input can come from anywhere, but typically comes from
47	// something like decoding JSON where we're not quite sure of the
48	// struct initially.
49	input := map[string]interface{}{
50		"name":   123,
51		"age":    "bad value",
52		"emails": []int{1, 2, 3},
53	}
54
55	var result Person
56	err := Decode(input, &result)
57	if err == nil {
58		panic("should have an error")
59	}
60
61	fmt.Println(err.Error())
62	// Output:
63	// 5 error(s) decoding:
64	//
65	// * 'Age' expected type 'int', got unconvertible type 'string', value: 'bad value'
66	// * 'Emails[0]' expected type 'string', got unconvertible type 'int', value: '1'
67	// * 'Emails[1]' expected type 'string', got unconvertible type 'int', value: '2'
68	// * 'Emails[2]' expected type 'string', got unconvertible type 'int', value: '3'
69	// * 'Name' expected type 'string', got unconvertible type 'int', value: '123'
70}
71
72func ExampleDecode_metadata() {
73	type Person struct {
74		Name string
75		Age  int
76	}
77
78	// This input can come from anywhere, but typically comes from
79	// something like decoding JSON where we're not quite sure of the
80	// struct initially.
81	input := map[string]interface{}{
82		"name":  "Mitchell",
83		"age":   91,
84		"email": "foo@bar.com",
85	}
86
87	// For metadata, we make a more advanced DecoderConfig so we can
88	// more finely configure the decoder that is used. In this case, we
89	// just tell the decoder we want to track metadata.
90	var md Metadata
91	var result Person
92	config := &DecoderConfig{
93		Metadata: &md,
94		Result:   &result,
95	}
96
97	decoder, err := NewDecoder(config)
98	if err != nil {
99		panic(err)
100	}
101
102	if err := decoder.Decode(input); err != nil {
103		panic(err)
104	}
105
106	fmt.Printf("Unused keys: %#v", md.Unused)
107	// Output:
108	// Unused keys: []string{"email"}
109}
110
111func ExampleDecode_weaklyTypedInput() {
112	type Person struct {
113		Name   string
114		Age    int
115		Emails []string
116	}
117
118	// This input can come from anywhere, but typically comes from
119	// something like decoding JSON, generated by a weakly typed language
120	// such as PHP.
121	input := map[string]interface{}{
122		"name":   123,                      // number => string
123		"age":    "42",                     // string => number
124		"emails": map[string]interface{}{}, // empty map => empty array
125	}
126
127	var result Person
128	config := &DecoderConfig{
129		WeaklyTypedInput: true,
130		Result:           &result,
131	}
132
133	decoder, err := NewDecoder(config)
134	if err != nil {
135		panic(err)
136	}
137
138	err = decoder.Decode(input)
139	if err != nil {
140		panic(err)
141	}
142
143	fmt.Printf("%#v", result)
144	// Output: mapstructure.Person{Name:"123", Age:42, Emails:[]string{}}
145}
146
147func ExampleDecode_tags() {
148	// Note that the mapstructure tags defined in the struct type
149	// can indicate which fields the values are mapped to.
150	type Person struct {
151		Name string `mapstructure:"person_name"`
152		Age  int    `mapstructure:"person_age"`
153	}
154
155	input := map[string]interface{}{
156		"person_name": "Mitchell",
157		"person_age":  91,
158	}
159
160	var result Person
161	err := Decode(input, &result)
162	if err != nil {
163		panic(err)
164	}
165
166	fmt.Printf("%#v", result)
167	// Output:
168	// mapstructure.Person{Name:"Mitchell", Age:91}
169}
170
171func ExampleDecode_embeddedStruct() {
172	// Squashing multiple embedded structs is allowed using the squash tag.
173	// This is demonstrated by creating a composite struct of multiple types
174	// and decoding into it. In this case, a person can carry with it both
175	// a Family and a Location, as well as their own FirstName.
176	type Family struct {
177		LastName string
178	}
179	type Location struct {
180		City string
181	}
182	type Person struct {
183		Family    `mapstructure:",squash"`
184		Location  `mapstructure:",squash"`
185		FirstName string
186	}
187
188	input := map[string]interface{}{
189		"FirstName": "Mitchell",
190		"LastName":  "Hashimoto",
191		"City":      "San Francisco",
192	}
193
194	var result Person
195	err := Decode(input, &result)
196	if err != nil {
197		panic(err)
198	}
199
200	fmt.Printf("%s %s, %s", result.FirstName, result.LastName, result.City)
201	// Output:
202	// Mitchell Hashimoto, San Francisco
203}
204
205func ExampleDecode_remainingData() {
206	// Note that the mapstructure tags defined in the struct type
207	// can indicate which fields the values are mapped to.
208	type Person struct {
209		Name  string
210		Age   int
211		Other map[string]interface{} `mapstructure:",remain"`
212	}
213
214	input := map[string]interface{}{
215		"name":  "Mitchell",
216		"age":   91,
217		"email": "mitchell@example.com",
218	}
219
220	var result Person
221	err := Decode(input, &result)
222	if err != nil {
223		panic(err)
224	}
225
226	fmt.Printf("%#v", result)
227	// Output:
228	// mapstructure.Person{Name:"Mitchell", Age:91, Other:map[string]interface {}{"email":"mitchell@example.com"}}
229}
230
231func ExampleDecode_omitempty() {
232	// Add omitempty annotation to avoid map keys for empty values
233	type Family struct {
234		LastName string
235	}
236	type Location struct {
237		City string
238	}
239	type Person struct {
240		*Family   `mapstructure:",omitempty"`
241		*Location `mapstructure:",omitempty"`
242		Age       int
243		FirstName string
244	}
245
246	result := &map[string]interface{}{}
247	input := Person{FirstName: "Somebody"}
248	err := Decode(input, &result)
249	if err != nil {
250		panic(err)
251	}
252
253	fmt.Printf("%+v", result)
254	// Output:
255	// &map[Age:0 FirstName:Somebody]
256}
257