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