mapstructure.go (45067B)
1 // Package mapstructure exposes functionality to convert one arbitrary 2 // Go type into another, typically to convert a map[string]interface{} 3 // into a native Go structure. 4 // 5 // The Go structure can be arbitrarily complex, containing slices, 6 // other structs, etc. and the decoder will properly decode nested 7 // maps and so on into the proper structures in the native Go struct. 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 struct { 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. 159 package mapstructure 160 161 import ( 162 "encoding/json" 163 "errors" 164 "fmt" 165 "reflect" 166 "sort" 167 "strconv" 168 "strings" 169 ) 170 171 // DecodeHookFunc is the callback function that can be used for 172 // data transformations. See "DecodeHook" in the DecoderConfig 173 // struct. 174 // 175 // The type must be one of DecodeHookFuncType, DecodeHookFuncKind, or 176 // DecodeHookFuncValue. 177 // Values are a superset of Types (Values can return types), and Types are a 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. 180 // 181 // The reason DecodeHookFunc is multi-typed is for backwards compatibility: 182 // we started with Kinds and then realized Types were the better solution, 183 // but have a promise to not break backwards compat so we now support 184 // both. 185 type DecodeHookFunc interface{} 186 187 // DecodeHookFuncType is a DecodeHookFunc which has complete information about 188 // the source and target types. 189 type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) 190 191 // DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the 192 // source and target types. 193 type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) 194 195 // DecodeHookFuncValue 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 199 // DecoderConfig is the configuration that is used to create a new decoder 200 // and allows customization of various aspects of decoding. 201 type DecoderConfig struct { 202 // DecodeHook, if set, will be called before any decoding and any 203 // type conversion (if WeaklyTypedInput is on). This lets you modify 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. 209 // 210 // If an error is returned, the entire decode will fail with that error. 211 DecodeHook DecodeHookFunc 212 213 // If ErrorUnused is true, then it is an error for there to exist 214 // keys in the original map that were unused in the decoding process 215 // (extra keys). 216 ErrorUnused bool 217 218 // If ErrorUnset is true, then it is an error for there to exist 219 // fields in the result that were not set in the decoding process 220 // (extra fields). This only applies to decoding to a struct. This 221 // will affect all nested structs as well. 222 ErrorUnset bool 223 224 // ZeroFields, if set to true, will zero fields before writing them. 225 // For example, a map will be emptied before decoded values are put in 226 // it. If this is false, a map will be merged. 227 ZeroFields bool 228 229 // If WeaklyTypedInput is true, the decoder will make the following 230 // "weak" conversions: 231 // 232 // - bools to string (true = "1", false = "0") 233 // - numbers to string (base 10) 234 // - bools to int/uint (true = 1, false = 0) 235 // - strings to int/uint (base implied by prefix) 236 // - int to bool (true if value != 0) 237 // - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F, 238 // FALSE, false, False. Anything else is an error) 239 // - empty array = empty map and vice versa 240 // - negative numbers to overflowed uint values (base 10) 241 // - slice of maps to a merged map 242 // - single values are converted to slices if required. Each 243 // element is weakly decoded. For example: "4" can become []int{4} 244 // if the target type is an int slice. 245 // 246 WeaklyTypedInput bool 247 248 // Squash will squash embedded structs. A squash tag may also be 249 // added to an individual struct field using a tag. For example: 250 // 251 // type Parent struct { 252 // Child `mapstructure:",squash"` 253 // } 254 Squash bool 255 256 // Metadata is the struct that will contain extra metadata about 257 // the decoding. If this is nil, then no metadata will be tracked. 258 Metadata *Metadata 259 260 // Result is a pointer to the struct that will contain the decoded 261 // value. 262 Result interface{} 263 264 // The tag name that mapstructure reads for field names. This 265 // defaults to "mapstructure" 266 TagName string 267 268 // IgnoreUntaggedFields ignores all struct fields without explicit 269 // TagName, comparable to `mapstructure:"-"` as default behaviour. 270 IgnoreUntaggedFields bool 271 272 // MatchName is the function used to match the map key to the struct 273 // field name or tag. Defaults to `strings.EqualFold`. This can be used 274 // to implement case-sensitive tag values, support snake casing, etc. 275 MatchName func(mapKey, fieldName string) bool 276 } 277 278 // A Decoder takes a raw interface value and turns it into structured 279 // data, keeping track of rich error information along the way in case 280 // anything goes wrong. Unlike the basic top-level Decode method, you can 281 // more finely control how the Decoder behaves using the DecoderConfig 282 // structure. The top-level Decode method is just a convenience that sets 283 // up the most basic Decoder. 284 type Decoder struct { 285 config *DecoderConfig 286 } 287 288 // Metadata contains information about decoding a structure that 289 // is tedious or difficult to get otherwise. 290 type Metadata struct { 291 // Keys are the keys of the structure which were successfully decoded 292 Keys []string 293 294 // Unused is a slice of keys that were found in the raw value but 295 // weren't decoded since there was no matching field in the result interface 296 Unused []string 297 298 // Unset is a slice of field names that were found in the result interface 299 // but weren't set in the decoding process since there was no matching value 300 // in the input 301 Unset []string 302 } 303 304 // Decode takes an input structure and uses reflection to translate it to 305 // the output structure. output must be a pointer to a map or struct. 306 func Decode(input interface{}, output interface{}) error { 307 config := &DecoderConfig{ 308 Metadata: nil, 309 Result: output, 310 } 311 312 decoder, err := NewDecoder(config) 313 if err != nil { 314 return err 315 } 316 317 return decoder.Decode(input) 318 } 319 320 // WeakDecode is the same as Decode but is shorthand to enable 321 // WeaklyTypedInput. See DecoderConfig for more info. 322 func WeakDecode(input, output interface{}) error { 323 config := &DecoderConfig{ 324 Metadata: nil, 325 Result: output, 326 WeaklyTypedInput: true, 327 } 328 329 decoder, err := NewDecoder(config) 330 if err != nil { 331 return err 332 } 333 334 return decoder.Decode(input) 335 } 336 337 // DecodeMetadata is the same as Decode, but is shorthand to 338 // enable metadata collection. See DecoderConfig for more info. 339 func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { 340 config := &DecoderConfig{ 341 Metadata: metadata, 342 Result: output, 343 } 344 345 decoder, err := NewDecoder(config) 346 if err != nil { 347 return err 348 } 349 350 return decoder.Decode(input) 351 } 352 353 // WeakDecodeMetadata is the same as Decode, but is shorthand to 354 // enable both WeaklyTypedInput and metadata collection. See 355 // DecoderConfig for more info. 356 func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { 357 config := &DecoderConfig{ 358 Metadata: metadata, 359 Result: output, 360 WeaklyTypedInput: true, 361 } 362 363 decoder, err := NewDecoder(config) 364 if err != nil { 365 return err 366 } 367 368 return decoder.Decode(input) 369 } 370 371 // NewDecoder returns a new decoder for the given configuration. Once 372 // a decoder has been returned, the same configuration must not be used 373 // again. 374 func NewDecoder(config *DecoderConfig) (*Decoder, error) { 375 val := reflect.ValueOf(config.Result) 376 if val.Kind() != reflect.Ptr { 377 return nil, errors.New("result must be a pointer") 378 } 379 380 val = val.Elem() 381 if !val.CanAddr() { 382 return nil, errors.New("result must be addressable (a pointer)") 383 } 384 385 if config.Metadata != nil { 386 if config.Metadata.Keys == nil { 387 config.Metadata.Keys = make([]string, 0) 388 } 389 390 if config.Metadata.Unused == nil { 391 config.Metadata.Unused = make([]string, 0) 392 } 393 394 if config.Metadata.Unset == nil { 395 config.Metadata.Unset = make([]string, 0) 396 } 397 } 398 399 if config.TagName == "" { 400 config.TagName = "mapstructure" 401 } 402 403 if config.MatchName == nil { 404 config.MatchName = strings.EqualFold 405 } 406 407 result := &Decoder{ 408 config: config, 409 } 410 411 return result, nil 412 } 413 414 // Decode decodes the given raw interface to the target pointer specified 415 // by the configuration. 416 func (d *Decoder) Decode(input interface{}) error { 417 return d.decode("", input, reflect.ValueOf(d.config.Result).Elem()) 418 } 419 420 // Decodes an unknown data type into a specific reflection value. 421 func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error { 422 var inputVal reflect.Value 423 if input != nil { 424 inputVal = reflect.ValueOf(input) 425 426 // We need to check here if input is a typed nil. Typed nils won't 427 // match the "input == nil" below so we check that here. 428 if inputVal.Kind() == reflect.Ptr && inputVal.IsNil() { 429 input = nil 430 } 431 } 432 433 if input == nil { 434 // If the data is nil, then we don't set anything, unless ZeroFields is set 435 // to true. 436 if d.config.ZeroFields { 437 outVal.Set(reflect.Zero(outVal.Type())) 438 439 if d.config.Metadata != nil && name != "" { 440 d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) 441 } 442 } 443 return nil 444 } 445 446 if !inputVal.IsValid() { 447 // If the input value is invalid, then we just set the value 448 // to be the zero value. 449 outVal.Set(reflect.Zero(outVal.Type())) 450 if d.config.Metadata != nil && name != "" { 451 d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) 452 } 453 return nil 454 } 455 456 if d.config.DecodeHook != nil { 457 // We have a DecodeHook, so let's pre-process the input. 458 var err error 459 input, err = DecodeHookExec(d.config.DecodeHook, inputVal, outVal) 460 if err != nil { 461 return fmt.Errorf("error decoding '%s': %s", name, err) 462 } 463 } 464 465 var err error 466 outputKind := getKind(outVal) 467 addMetaKey := true 468 switch outputKind { 469 case reflect.Bool: 470 err = d.decodeBool(name, input, outVal) 471 case reflect.Interface: 472 err = d.decodeBasic(name, input, outVal) 473 case reflect.String: 474 err = d.decodeString(name, input, outVal) 475 case reflect.Int: 476 err = d.decodeInt(name, input, outVal) 477 case reflect.Uint: 478 err = d.decodeUint(name, input, outVal) 479 case reflect.Float32: 480 err = d.decodeFloat(name, input, outVal) 481 case reflect.Struct: 482 err = d.decodeStruct(name, input, outVal) 483 case reflect.Map: 484 err = d.decodeMap(name, input, outVal) 485 case reflect.Ptr: 486 addMetaKey, err = d.decodePtr(name, input, outVal) 487 case reflect.Slice: 488 err = d.decodeSlice(name, input, outVal) 489 case reflect.Array: 490 err = d.decodeArray(name, input, outVal) 491 case reflect.Func: 492 err = d.decodeFunc(name, input, outVal) 493 default: 494 // If we reached this point then we weren't able to decode it 495 return fmt.Errorf("%s: unsupported type: %s", name, outputKind) 496 } 497 498 // If we reached here, then we successfully decoded SOMETHING, so 499 // mark the key as used if we're tracking metainput. 500 if addMetaKey && d.config.Metadata != nil && name != "" { 501 d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) 502 } 503 504 return err 505 } 506 507 // This decodes a basic type (bool, int, string, etc.) and sets the 508 // value to "data" of that type. 509 func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { 510 if val.IsValid() && val.Elem().IsValid() { 511 elem := val.Elem() 512 513 // If we can't address this element, then its not writable. Instead, 514 // we make a copy of the value (which is a pointer and therefore 515 // writable), decode into that, and replace the whole value. 516 copied := false 517 if !elem.CanAddr() { 518 copied = true 519 520 // Make *T 521 copy := reflect.New(elem.Type()) 522 523 // *T = elem 524 copy.Elem().Set(elem) 525 526 // Set elem so we decode into it 527 elem = copy 528 } 529 530 // Decode. If we have an error then return. We also return right 531 // away if we're not a copy because that means we decoded directly. 532 if err := d.decode(name, data, elem); err != nil || !copied { 533 return err 534 } 535 536 // If we're a copy, we need to set te final result 537 val.Set(elem.Elem()) 538 return nil 539 } 540 541 dataVal := reflect.ValueOf(data) 542 543 // If the input data is a pointer, and the assigned type is the dereference 544 // of that exact pointer, then indirect it so that we can assign it. 545 // Example: *string to string 546 if dataVal.Kind() == reflect.Ptr && dataVal.Type().Elem() == val.Type() { 547 dataVal = reflect.Indirect(dataVal) 548 } 549 550 if !dataVal.IsValid() { 551 dataVal = reflect.Zero(val.Type()) 552 } 553 554 dataValType := dataVal.Type() 555 if !dataValType.AssignableTo(val.Type()) { 556 return fmt.Errorf( 557 "'%s' expected type '%s', got '%s'", 558 name, val.Type(), dataValType) 559 } 560 561 val.Set(dataVal) 562 return nil 563 } 564 565 func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { 566 dataVal := reflect.Indirect(reflect.ValueOf(data)) 567 dataKind := getKind(dataVal) 568 569 converted := true 570 switch { 571 case dataKind == reflect.String: 572 val.SetString(dataVal.String()) 573 case dataKind == reflect.Bool && d.config.WeaklyTypedInput: 574 if dataVal.Bool() { 575 val.SetString("1") 576 } else { 577 val.SetString("0") 578 } 579 case dataKind == reflect.Int && d.config.WeaklyTypedInput: 580 val.SetString(strconv.FormatInt(dataVal.Int(), 10)) 581 case dataKind == reflect.Uint && d.config.WeaklyTypedInput: 582 val.SetString(strconv.FormatUint(dataVal.Uint(), 10)) 583 case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: 584 val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64)) 585 case dataKind == reflect.Slice && d.config.WeaklyTypedInput, 586 dataKind == reflect.Array && d.config.WeaklyTypedInput: 587 dataType := dataVal.Type() 588 elemKind := dataType.Elem().Kind() 589 switch elemKind { 590 case reflect.Uint8: 591 var uints []uint8 592 if dataKind == reflect.Array { 593 uints = make([]uint8, dataVal.Len(), dataVal.Len()) 594 for i := range uints { 595 uints[i] = dataVal.Index(i).Interface().(uint8) 596 } 597 } else { 598 uints = dataVal.Interface().([]uint8) 599 } 600 val.SetString(string(uints)) 601 default: 602 converted = false 603 } 604 default: 605 converted = false 606 } 607 608 if !converted { 609 return fmt.Errorf( 610 "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", 611 name, val.Type(), dataVal.Type(), data) 612 } 613 614 return nil 615 } 616 617 func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { 618 dataVal := reflect.Indirect(reflect.ValueOf(data)) 619 dataKind := getKind(dataVal) 620 dataType := dataVal.Type() 621 622 switch { 623 case dataKind == reflect.Int: 624 val.SetInt(dataVal.Int()) 625 case dataKind == reflect.Uint: 626 val.SetInt(int64(dataVal.Uint())) 627 case dataKind == reflect.Float32: 628 val.SetInt(int64(dataVal.Float())) 629 case dataKind == reflect.Bool && d.config.WeaklyTypedInput: 630 if dataVal.Bool() { 631 val.SetInt(1) 632 } else { 633 val.SetInt(0) 634 } 635 case dataKind == reflect.String && d.config.WeaklyTypedInput: 636 str := dataVal.String() 637 if str == "" { 638 str = "0" 639 } 640 641 i, err := strconv.ParseInt(str, 0, val.Type().Bits()) 642 if err == nil { 643 val.SetInt(i) 644 } else { 645 return fmt.Errorf("cannot parse '%s' as int: %s", name, err) 646 } 647 case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": 648 jn := data.(json.Number) 649 i, err := jn.Int64() 650 if err != nil { 651 return fmt.Errorf( 652 "error decoding json.Number into %s: %s", name, err) 653 } 654 val.SetInt(i) 655 default: 656 return fmt.Errorf( 657 "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", 658 name, val.Type(), dataVal.Type(), data) 659 } 660 661 return nil 662 } 663 664 func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { 665 dataVal := reflect.Indirect(reflect.ValueOf(data)) 666 dataKind := getKind(dataVal) 667 dataType := dataVal.Type() 668 669 switch { 670 case dataKind == reflect.Int: 671 i := dataVal.Int() 672 if i < 0 && !d.config.WeaklyTypedInput { 673 return fmt.Errorf("cannot parse '%s', %d overflows uint", 674 name, i) 675 } 676 val.SetUint(uint64(i)) 677 case dataKind == reflect.Uint: 678 val.SetUint(dataVal.Uint()) 679 case dataKind == reflect.Float32: 680 f := dataVal.Float() 681 if f < 0 && !d.config.WeaklyTypedInput { 682 return fmt.Errorf("cannot parse '%s', %f overflows uint", 683 name, f) 684 } 685 val.SetUint(uint64(f)) 686 case dataKind == reflect.Bool && d.config.WeaklyTypedInput: 687 if dataVal.Bool() { 688 val.SetUint(1) 689 } else { 690 val.SetUint(0) 691 } 692 case dataKind == reflect.String && d.config.WeaklyTypedInput: 693 str := dataVal.String() 694 if str == "" { 695 str = "0" 696 } 697 698 i, err := strconv.ParseUint(str, 0, val.Type().Bits()) 699 if err == nil { 700 val.SetUint(i) 701 } else { 702 return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) 703 } 704 case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": 705 jn := data.(json.Number) 706 i, err := strconv.ParseUint(string(jn), 0, 64) 707 if err != nil { 708 return fmt.Errorf( 709 "error decoding json.Number into %s: %s", name, err) 710 } 711 val.SetUint(i) 712 default: 713 return fmt.Errorf( 714 "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", 715 name, val.Type(), dataVal.Type(), data) 716 } 717 718 return nil 719 } 720 721 func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { 722 dataVal := reflect.Indirect(reflect.ValueOf(data)) 723 dataKind := getKind(dataVal) 724 725 switch { 726 case dataKind == reflect.Bool: 727 val.SetBool(dataVal.Bool()) 728 case dataKind == reflect.Int && d.config.WeaklyTypedInput: 729 val.SetBool(dataVal.Int() != 0) 730 case dataKind == reflect.Uint && d.config.WeaklyTypedInput: 731 val.SetBool(dataVal.Uint() != 0) 732 case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: 733 val.SetBool(dataVal.Float() != 0) 734 case dataKind == reflect.String && d.config.WeaklyTypedInput: 735 b, err := strconv.ParseBool(dataVal.String()) 736 if err == nil { 737 val.SetBool(b) 738 } else if dataVal.String() == "" { 739 val.SetBool(false) 740 } else { 741 return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) 742 } 743 default: 744 return fmt.Errorf( 745 "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", 746 name, val.Type(), dataVal.Type(), data) 747 } 748 749 return nil 750 } 751 752 func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { 753 dataVal := reflect.Indirect(reflect.ValueOf(data)) 754 dataKind := getKind(dataVal) 755 dataType := dataVal.Type() 756 757 switch { 758 case dataKind == reflect.Int: 759 val.SetFloat(float64(dataVal.Int())) 760 case dataKind == reflect.Uint: 761 val.SetFloat(float64(dataVal.Uint())) 762 case dataKind == reflect.Float32: 763 val.SetFloat(dataVal.Float()) 764 case dataKind == reflect.Bool && d.config.WeaklyTypedInput: 765 if dataVal.Bool() { 766 val.SetFloat(1) 767 } else { 768 val.SetFloat(0) 769 } 770 case dataKind == reflect.String && d.config.WeaklyTypedInput: 771 str := dataVal.String() 772 if str == "" { 773 str = "0" 774 } 775 776 f, err := strconv.ParseFloat(str, val.Type().Bits()) 777 if err == nil { 778 val.SetFloat(f) 779 } else { 780 return fmt.Errorf("cannot parse '%s' as float: %s", name, err) 781 } 782 case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": 783 jn := data.(json.Number) 784 i, err := jn.Float64() 785 if err != nil { 786 return fmt.Errorf( 787 "error decoding json.Number into %s: %s", name, err) 788 } 789 val.SetFloat(i) 790 default: 791 return fmt.Errorf( 792 "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", 793 name, val.Type(), dataVal.Type(), data) 794 } 795 796 return nil 797 } 798 799 func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { 800 valType := val.Type() 801 valKeyType := valType.Key() 802 valElemType := valType.Elem() 803 804 // By default we overwrite keys in the current map 805 valMap := val 806 807 // If the map is nil or we're purposely zeroing fields, make a new map 808 if valMap.IsNil() || d.config.ZeroFields { 809 // Make a new map to hold our result 810 mapType := reflect.MapOf(valKeyType, valElemType) 811 valMap = reflect.MakeMap(mapType) 812 } 813 814 // Check input type and based on the input type jump to the proper func 815 dataVal := reflect.Indirect(reflect.ValueOf(data)) 816 switch dataVal.Kind() { 817 case reflect.Map: 818 return d.decodeMapFromMap(name, dataVal, val, valMap) 819 820 case reflect.Struct: 821 return d.decodeMapFromStruct(name, dataVal, val, valMap) 822 823 case reflect.Array, reflect.Slice: 824 if d.config.WeaklyTypedInput { 825 return d.decodeMapFromSlice(name, dataVal, val, valMap) 826 } 827 828 fallthrough 829 830 default: 831 return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) 832 } 833 } 834 835 func (d *Decoder) decodeMapFromSlice(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { 836 // Special case for BC reasons (covered by tests) 837 if dataVal.Len() == 0 { 838 val.Set(valMap) 839 return nil 840 } 841 842 for i := 0; i < dataVal.Len(); i++ { 843 err := d.decode( 844 name+"["+strconv.Itoa(i)+"]", 845 dataVal.Index(i).Interface(), val) 846 if err != nil { 847 return err 848 } 849 } 850 851 return nil 852 } 853 854 func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { 855 valType := val.Type() 856 valKeyType := valType.Key() 857 valElemType := valType.Elem() 858 859 // Accumulate errors 860 errors := make([]string, 0) 861 862 // If the input data is empty, then we just match what the input data is. 863 if dataVal.Len() == 0 { 864 if dataVal.IsNil() { 865 if !val.IsNil() { 866 val.Set(dataVal) 867 } 868 } else { 869 // Set to empty allocated value 870 val.Set(valMap) 871 } 872 873 return nil 874 } 875 876 for _, k := range dataVal.MapKeys() { 877 fieldName := name + "[" + k.String() + "]" 878 879 // First decode the key into the proper type 880 currentKey := reflect.Indirect(reflect.New(valKeyType)) 881 if err := d.decode(fieldName, k.Interface(), currentKey); err != nil { 882 errors = appendErrors(errors, err) 883 continue 884 } 885 886 // Next decode the data into the proper type 887 v := dataVal.MapIndex(k).Interface() 888 currentVal := reflect.Indirect(reflect.New(valElemType)) 889 if err := d.decode(fieldName, v, currentVal); err != nil { 890 errors = appendErrors(errors, err) 891 continue 892 } 893 894 valMap.SetMapIndex(currentKey, currentVal) 895 } 896 897 // Set the built up map to the value 898 val.Set(valMap) 899 900 // If we had errors, return those 901 if len(errors) > 0 { 902 return &Error{errors} 903 } 904 905 return nil 906 } 907 908 func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { 909 typ := dataVal.Type() 910 for i := 0; i < typ.NumField(); i++ { 911 // Get the StructField first since this is a cheap operation. If the 912 // field is unexported, then ignore it. 913 f := typ.Field(i) 914 if f.PkgPath != "" { 915 continue 916 } 917 918 // Next get the actual value of this field and verify it is assignable 919 // to the map value. 920 v := dataVal.Field(i) 921 if !v.Type().AssignableTo(valMap.Type().Elem()) { 922 return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem()) 923 } 924 925 tagValue := f.Tag.Get(d.config.TagName) 926 keyName := f.Name 927 928 if tagValue == "" && d.config.IgnoreUntaggedFields { 929 continue 930 } 931 932 // If Squash is set in the config, we squash the field down. 933 squash := d.config.Squash && v.Kind() == reflect.Struct && f.Anonymous 934 935 v = dereferencePtrToStructIfNeeded(v, d.config.TagName) 936 937 // Determine the name of the key in the map 938 if index := strings.Index(tagValue, ","); index != -1 { 939 if tagValue[:index] == "-" { 940 continue 941 } 942 // If "omitempty" is specified in the tag, it ignores empty values. 943 if strings.Index(tagValue[index+1:], "omitempty") != -1 && isEmptyValue(v) { 944 continue 945 } 946 947 // If "squash" is specified in the tag, we squash the field down. 948 squash = squash || strings.Index(tagValue[index+1:], "squash") != -1 949 if squash { 950 // When squashing, the embedded type can be a pointer to a struct. 951 if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { 952 v = v.Elem() 953 } 954 955 // The final type must be a struct 956 if v.Kind() != reflect.Struct { 957 return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) 958 } 959 } 960 if keyNameTagValue := tagValue[:index]; keyNameTagValue != "" { 961 keyName = keyNameTagValue 962 } 963 } else if len(tagValue) > 0 { 964 if tagValue == "-" { 965 continue 966 } 967 keyName = tagValue 968 } 969 970 switch v.Kind() { 971 // this is an embedded struct, so handle it differently 972 case reflect.Struct: 973 x := reflect.New(v.Type()) 974 x.Elem().Set(v) 975 976 vType := valMap.Type() 977 vKeyType := vType.Key() 978 vElemType := vType.Elem() 979 mType := reflect.MapOf(vKeyType, vElemType) 980 vMap := reflect.MakeMap(mType) 981 982 // Creating a pointer to a map so that other methods can completely 983 // overwrite the map if need be (looking at you decodeMapFromMap). The 984 // indirection allows the underlying map to be settable (CanSet() == true) 985 // where as reflect.MakeMap returns an unsettable map. 986 addrVal := reflect.New(vMap.Type()) 987 reflect.Indirect(addrVal).Set(vMap) 988 989 err := d.decode(keyName, x.Interface(), reflect.Indirect(addrVal)) 990 if err != nil { 991 return err 992 } 993 994 // the underlying map may have been completely overwritten so pull 995 // it indirectly out of the enclosing value. 996 vMap = reflect.Indirect(addrVal) 997 998 if squash { 999 for _, k := range vMap.MapKeys() { 1000 valMap.SetMapIndex(k, vMap.MapIndex(k)) 1001 } 1002 } else { 1003 valMap.SetMapIndex(reflect.ValueOf(keyName), vMap) 1004 } 1005 1006 default: 1007 valMap.SetMapIndex(reflect.ValueOf(keyName), v) 1008 } 1009 } 1010 1011 if val.CanAddr() { 1012 val.Set(valMap) 1013 } 1014 1015 return nil 1016 } 1017 1018 func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) { 1019 // If the input data is nil, then we want to just set the output 1020 // pointer to be nil as well. 1021 isNil := data == nil 1022 if !isNil { 1023 switch v := reflect.Indirect(reflect.ValueOf(data)); v.Kind() { 1024 case reflect.Chan, 1025 reflect.Func, 1026 reflect.Interface, 1027 reflect.Map, 1028 reflect.Ptr, 1029 reflect.Slice: 1030 isNil = v.IsNil() 1031 } 1032 } 1033 if isNil { 1034 if !val.IsNil() && val.CanSet() { 1035 nilValue := reflect.New(val.Type()).Elem() 1036 val.Set(nilValue) 1037 } 1038 1039 return true, nil 1040 } 1041 1042 // Create an element of the concrete (non pointer) type and decode 1043 // into that. Then set the value of the pointer to this type. 1044 valType := val.Type() 1045 valElemType := valType.Elem() 1046 if val.CanSet() { 1047 realVal := val 1048 if realVal.IsNil() || d.config.ZeroFields { 1049 realVal = reflect.New(valElemType) 1050 } 1051 1052 if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { 1053 return false, err 1054 } 1055 1056 val.Set(realVal) 1057 } else { 1058 if err := d.decode(name, data, reflect.Indirect(val)); err != nil { 1059 return false, err 1060 } 1061 } 1062 return false, nil 1063 } 1064 1065 func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error { 1066 // Create an element of the concrete (non pointer) type and decode 1067 // into that. Then set the value of the pointer to this type. 1068 dataVal := reflect.Indirect(reflect.ValueOf(data)) 1069 if val.Type() != dataVal.Type() { 1070 return fmt.Errorf( 1071 "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", 1072 name, val.Type(), dataVal.Type(), data) 1073 } 1074 val.Set(dataVal) 1075 return nil 1076 } 1077 1078 func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { 1079 dataVal := reflect.Indirect(reflect.ValueOf(data)) 1080 dataValKind := dataVal.Kind() 1081 valType := val.Type() 1082 valElemType := valType.Elem() 1083 sliceType := reflect.SliceOf(valElemType) 1084 1085 // If we have a non array/slice type then we first attempt to convert. 1086 if dataValKind != reflect.Array && dataValKind != reflect.Slice { 1087 if d.config.WeaklyTypedInput { 1088 switch { 1089 // Slice and array we use the normal logic 1090 case dataValKind == reflect.Slice, dataValKind == reflect.Array: 1091 break 1092 1093 // Empty maps turn into empty slices 1094 case dataValKind == reflect.Map: 1095 if dataVal.Len() == 0 { 1096 val.Set(reflect.MakeSlice(sliceType, 0, 0)) 1097 return nil 1098 } 1099 // Create slice of maps of other sizes 1100 return d.decodeSlice(name, []interface{}{data}, val) 1101 1102 case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8: 1103 return d.decodeSlice(name, []byte(dataVal.String()), val) 1104 1105 // All other types we try to convert to the slice type 1106 // and "lift" it into it. i.e. a string becomes a string slice. 1107 default: 1108 // Just re-try this function with data as a slice. 1109 return d.decodeSlice(name, []interface{}{data}, val) 1110 } 1111 } 1112 1113 return fmt.Errorf( 1114 "'%s': source data must be an array or slice, got %s", name, dataValKind) 1115 } 1116 1117 // If the input value is nil, then don't allocate since empty != nil 1118 if dataValKind != reflect.Array && dataVal.IsNil() { 1119 return nil 1120 } 1121 1122 valSlice := val 1123 if valSlice.IsNil() || d.config.ZeroFields { 1124 // Make a new slice to hold our result, same size as the original data. 1125 valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) 1126 } 1127 1128 // Accumulate any errors 1129 errors := make([]string, 0) 1130 1131 for i := 0; i < dataVal.Len(); i++ { 1132 currentData := dataVal.Index(i).Interface() 1133 for valSlice.Len() <= i { 1134 valSlice = reflect.Append(valSlice, reflect.Zero(valElemType)) 1135 } 1136 currentField := valSlice.Index(i) 1137 1138 fieldName := name + "[" + strconv.Itoa(i) + "]" 1139 if err := d.decode(fieldName, currentData, currentField); err != nil { 1140 errors = appendErrors(errors, err) 1141 } 1142 } 1143 1144 // Finally, set the value to the slice we built up 1145 val.Set(valSlice) 1146 1147 // If there were errors, we return those 1148 if len(errors) > 0 { 1149 return &Error{errors} 1150 } 1151 1152 return nil 1153 } 1154 1155 func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error { 1156 dataVal := reflect.Indirect(reflect.ValueOf(data)) 1157 dataValKind := dataVal.Kind() 1158 valType := val.Type() 1159 valElemType := valType.Elem() 1160 arrayType := reflect.ArrayOf(valType.Len(), valElemType) 1161 1162 valArray := val 1163 1164 if valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields { 1165 // Check input type 1166 if dataValKind != reflect.Array && dataValKind != reflect.Slice { 1167 if d.config.WeaklyTypedInput { 1168 switch { 1169 // Empty maps turn into empty arrays 1170 case dataValKind == reflect.Map: 1171 if dataVal.Len() == 0 { 1172 val.Set(reflect.Zero(arrayType)) 1173 return nil 1174 } 1175 1176 // All other types we try to convert to the array type 1177 // and "lift" it into it. i.e. a string becomes a string array. 1178 default: 1179 // Just re-try this function with data as a slice. 1180 return d.decodeArray(name, []interface{}{data}, val) 1181 } 1182 } 1183 1184 return fmt.Errorf( 1185 "'%s': source data must be an array or slice, got %s", name, dataValKind) 1186 1187 } 1188 if dataVal.Len() > arrayType.Len() { 1189 return fmt.Errorf( 1190 "'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len()) 1191 1192 } 1193 1194 // Make a new array to hold our result, same size as the original data. 1195 valArray = reflect.New(arrayType).Elem() 1196 } 1197 1198 // Accumulate any errors 1199 errors := make([]string, 0) 1200 1201 for i := 0; i < dataVal.Len(); i++ { 1202 currentData := dataVal.Index(i).Interface() 1203 currentField := valArray.Index(i) 1204 1205 fieldName := name + "[" + strconv.Itoa(i) + "]" 1206 if err := d.decode(fieldName, currentData, currentField); err != nil { 1207 errors = appendErrors(errors, err) 1208 } 1209 } 1210 1211 // Finally, set the value to the array we built up 1212 val.Set(valArray) 1213 1214 // If there were errors, we return those 1215 if len(errors) > 0 { 1216 return &Error{errors} 1217 } 1218 1219 return nil 1220 } 1221 1222 func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { 1223 dataVal := reflect.Indirect(reflect.ValueOf(data)) 1224 1225 // If the type of the value to write to and the data match directly, 1226 // then we just set it directly instead of recursing into the structure. 1227 if dataVal.Type() == val.Type() { 1228 val.Set(dataVal) 1229 return nil 1230 } 1231 1232 dataValKind := dataVal.Kind() 1233 switch dataValKind { 1234 case reflect.Map: 1235 return d.decodeStructFromMap(name, dataVal, val) 1236 1237 case reflect.Struct: 1238 // Not the most efficient way to do this but we can optimize later if 1239 // we want to. To convert from struct to struct we go to map first 1240 // as an intermediary. 1241 1242 // Make a new map to hold our result 1243 mapType := reflect.TypeOf((map[string]interface{})(nil)) 1244 mval := reflect.MakeMap(mapType) 1245 1246 // Creating a pointer to a map so that other methods can completely 1247 // overwrite the map if need be (looking at you decodeMapFromMap). The 1248 // indirection allows the underlying map to be settable (CanSet() == true) 1249 // where as reflect.MakeMap returns an unsettable map. 1250 addrVal := reflect.New(mval.Type()) 1251 1252 reflect.Indirect(addrVal).Set(mval) 1253 if err := d.decodeMapFromStruct(name, dataVal, reflect.Indirect(addrVal), mval); err != nil { 1254 return err 1255 } 1256 1257 result := d.decodeStructFromMap(name, reflect.Indirect(addrVal), val) 1258 return result 1259 1260 default: 1261 return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) 1262 } 1263 } 1264 1265 func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error { 1266 dataValType := dataVal.Type() 1267 if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { 1268 return fmt.Errorf( 1269 "'%s' needs a map with string keys, has '%s' keys", 1270 name, dataValType.Key().Kind()) 1271 } 1272 1273 dataValKeys := make(map[reflect.Value]struct{}) 1274 dataValKeysUnused := make(map[interface{}]struct{}) 1275 for _, dataValKey := range dataVal.MapKeys() { 1276 dataValKeys[dataValKey] = struct{}{} 1277 dataValKeysUnused[dataValKey.Interface()] = struct{}{} 1278 } 1279 1280 targetValKeysUnused := make(map[interface{}]struct{}) 1281 errors := make([]string, 0) 1282 1283 // This slice will keep track of all the structs we'll be decoding. 1284 // There can be more than one struct if there are embedded structs 1285 // that are squashed. 1286 structs := make([]reflect.Value, 1, 5) 1287 structs[0] = val 1288 1289 // Compile the list of all the fields that we're going to be decoding 1290 // from all the structs. 1291 type field struct { 1292 field reflect.StructField 1293 val reflect.Value 1294 } 1295 1296 // remainField is set to a valid field set with the "remain" tag if 1297 // we are keeping track of remaining values. 1298 var remainField *field 1299 1300 fields := []field{} 1301 for len(structs) > 0 { 1302 structVal := structs[0] 1303 structs = structs[1:] 1304 1305 structType := structVal.Type() 1306 1307 for i := 0; i < structType.NumField(); i++ { 1308 fieldType := structType.Field(i) 1309 fieldVal := structVal.Field(i) 1310 if fieldVal.Kind() == reflect.Ptr && fieldVal.Elem().Kind() == reflect.Struct { 1311 // Handle embedded struct pointers as embedded structs. 1312 fieldVal = fieldVal.Elem() 1313 } 1314 1315 // If "squash" is specified in the tag, we squash the field down. 1316 squash := d.config.Squash && fieldVal.Kind() == reflect.Struct && fieldType.Anonymous 1317 remain := false 1318 1319 // We always parse the tags cause we're looking for other tags too 1320 tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") 1321 for _, tag := range tagParts[1:] { 1322 if tag == "squash" { 1323 squash = true 1324 break 1325 } 1326 1327 if tag == "remain" { 1328 remain = true 1329 break 1330 } 1331 } 1332 1333 if squash { 1334 if fieldVal.Kind() != reflect.Struct { 1335 errors = appendErrors(errors, 1336 fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind())) 1337 } else { 1338 structs = append(structs, fieldVal) 1339 } 1340 continue 1341 } 1342 1343 // Build our field 1344 if remain { 1345 remainField = &field{fieldType, fieldVal} 1346 } else { 1347 // Normal struct field, store it away 1348 fields = append(fields, field{fieldType, fieldVal}) 1349 } 1350 } 1351 } 1352 1353 // for fieldType, field := range fields { 1354 for _, f := range fields { 1355 field, fieldValue := f.field, f.val 1356 fieldName := field.Name 1357 1358 tagValue := field.Tag.Get(d.config.TagName) 1359 tagValue = strings.SplitN(tagValue, ",", 2)[0] 1360 if tagValue != "" { 1361 fieldName = tagValue 1362 } 1363 1364 rawMapKey := reflect.ValueOf(fieldName) 1365 rawMapVal := dataVal.MapIndex(rawMapKey) 1366 if !rawMapVal.IsValid() { 1367 // Do a slower search by iterating over each key and 1368 // doing case-insensitive search. 1369 for dataValKey := range dataValKeys { 1370 mK, ok := dataValKey.Interface().(string) 1371 if !ok { 1372 // Not a string key 1373 continue 1374 } 1375 1376 if d.config.MatchName(mK, fieldName) { 1377 rawMapKey = dataValKey 1378 rawMapVal = dataVal.MapIndex(dataValKey) 1379 break 1380 } 1381 } 1382 1383 if !rawMapVal.IsValid() { 1384 // There was no matching key in the map for the value in 1385 // the struct. Remember it for potential errors and metadata. 1386 targetValKeysUnused[fieldName] = struct{}{} 1387 continue 1388 } 1389 } 1390 1391 if !fieldValue.IsValid() { 1392 // This should never happen 1393 panic("field is not valid") 1394 } 1395 1396 // If we can't set the field, then it is unexported or something, 1397 // and we just continue onwards. 1398 if !fieldValue.CanSet() { 1399 continue 1400 } 1401 1402 // Delete the key we're using from the unused map so we stop tracking 1403 delete(dataValKeysUnused, rawMapKey.Interface()) 1404 1405 // If the name is empty string, then we're at the root, and we 1406 // don't dot-join the fields. 1407 if name != "" { 1408 fieldName = name + "." + fieldName 1409 } 1410 1411 if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil { 1412 errors = appendErrors(errors, err) 1413 } 1414 } 1415 1416 // If we have a "remain"-tagged field and we have unused keys then 1417 // we put the unused keys directly into the remain field. 1418 if remainField != nil && len(dataValKeysUnused) > 0 { 1419 // Build a map of only the unused values 1420 remain := map[interface{}]interface{}{} 1421 for key := range dataValKeysUnused { 1422 remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface() 1423 } 1424 1425 // Decode it as-if we were just decoding this map onto our map. 1426 if err := d.decodeMap(name, remain, remainField.val); err != nil { 1427 errors = appendErrors(errors, err) 1428 } 1429 1430 // Set the map to nil so we have none so that the next check will 1431 // not error (ErrorUnused) 1432 dataValKeysUnused = nil 1433 } 1434 1435 if d.config.ErrorUnused && len(dataValKeysUnused) > 0 { 1436 keys := make([]string, 0, len(dataValKeysUnused)) 1437 for rawKey := range dataValKeysUnused { 1438 keys = append(keys, rawKey.(string)) 1439 } 1440 sort.Strings(keys) 1441 1442 err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) 1443 errors = appendErrors(errors, err) 1444 } 1445 1446 if d.config.ErrorUnset && len(targetValKeysUnused) > 0 { 1447 keys := make([]string, 0, len(targetValKeysUnused)) 1448 for rawKey := range targetValKeysUnused { 1449 keys = append(keys, rawKey.(string)) 1450 } 1451 sort.Strings(keys) 1452 1453 err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", ")) 1454 errors = appendErrors(errors, err) 1455 } 1456 1457 if len(errors) > 0 { 1458 return &Error{errors} 1459 } 1460 1461 // Add the unused keys to the list of unused keys if we're tracking metadata 1462 if d.config.Metadata != nil { 1463 for rawKey := range dataValKeysUnused { 1464 key := rawKey.(string) 1465 if name != "" { 1466 key = name + "." + key 1467 } 1468 1469 d.config.Metadata.Unused = append(d.config.Metadata.Unused, key) 1470 } 1471 for rawKey := range targetValKeysUnused { 1472 key := rawKey.(string) 1473 if name != "" { 1474 key = name + "." + key 1475 } 1476 1477 d.config.Metadata.Unset = append(d.config.Metadata.Unset, key) 1478 } 1479 } 1480 1481 return nil 1482 } 1483 1484 func isEmptyValue(v reflect.Value) bool { 1485 switch getKind(v) { 1486 case reflect.Array, reflect.Map, reflect.Slice, reflect.String: 1487 return v.Len() == 0 1488 case reflect.Bool: 1489 return !v.Bool() 1490 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 1491 return v.Int() == 0 1492 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 1493 return v.Uint() == 0 1494 case reflect.Float32, reflect.Float64: 1495 return v.Float() == 0 1496 case reflect.Interface, reflect.Ptr: 1497 return v.IsNil() 1498 } 1499 return false 1500 } 1501 1502 func getKind(val reflect.Value) reflect.Kind { 1503 kind := val.Kind() 1504 1505 switch { 1506 case kind >= reflect.Int && kind <= reflect.Int64: 1507 return reflect.Int 1508 case kind >= reflect.Uint && kind <= reflect.Uint64: 1509 return reflect.Uint 1510 case kind >= reflect.Float32 && kind <= reflect.Float64: 1511 return reflect.Float32 1512 default: 1513 return kind 1514 } 1515 } 1516 1517 func isStructTypeConvertibleToMap(typ reflect.Type, checkMapstructureTags bool, tagName string) bool { 1518 for i := 0; i < typ.NumField(); i++ { 1519 f := typ.Field(i) 1520 if f.PkgPath == "" && !checkMapstructureTags { // check for unexported fields 1521 return true 1522 } 1523 if checkMapstructureTags && f.Tag.Get(tagName) != "" { // check for mapstructure tags inside 1524 return true 1525 } 1526 } 1527 return false 1528 } 1529 1530 func dereferencePtrToStructIfNeeded(v reflect.Value, tagName string) reflect.Value { 1531 if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct { 1532 return v 1533 } 1534 deref := v.Elem() 1535 derefT := deref.Type() 1536 if isStructTypeConvertibleToMap(derefT, true, tagName) { 1537 return deref 1538 } 1539 return v 1540 }