1// Package mapstructure exposes functionality to convert an arbitrary 2// map[string]interface{} into a native Go structure. 3// 4// The Go structure can be arbitrarily complex, containing slices, 5// 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// See the examples to see what the decoder is capable of. 8package mapstructure 9 10import ( 11 "encoding/json" 12 "errors" 13 "fmt" 14 "reflect" 15 "sort" 16 "strconv" 17 "strings" 18) 19 20// DecodeHookFunc is the callback function that can be used for 21// data transformations. See "DecodeHook" in the DecoderConfig 22// struct. 23// 24// The type should be DecodeHookFuncType or DecodeHookFuncKind. 25// Either is accepted. Types are a superset of Kinds (Types can return 26// Kinds) and are generally a richer thing to use, but Kinds are simpler 27// if you only need those. 28// 29// The reason DecodeHookFunc is multi-typed is for backwards compatibility: 30// 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 32// both. 33type DecodeHookFunc interface{} 34 35// DecodeHookFuncType is a DecodeHookFunc which has complete information about 36// the source and target types. 37type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) 38 39// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the 40// source and target types. 41type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) 42 43// DecoderConfig is the configuration that is used to create a new decoder 44// and allows customization of various aspects of decoding. 45type DecoderConfig struct { 46 // DecodeHook, if set, will be called before any decoding and any 47 // type conversion (if WeaklyTypedInput is on). This lets you modify 48 // the values before they're set down onto the resulting struct. 49 // 50 // If an error is returned, the entire decode will fail with that 51 // error. 52 DecodeHook DecodeHookFunc 53 54 // 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 56 // (extra keys). 57 ErrorUnused bool 58 59 // ZeroFields, if set to true, will zero fields before writing them. 60 // For example, a map will be emptied before decoded values are put in 61 // it. If this is false, a map will be merged. 62 ZeroFields bool 63 64 // If WeaklyTypedInput is true, the decoder will make the following 65 // "weak" conversions: 66 // 67 // - bools to string (true = "1", false = "0") 68 // - numbers to string (base 10) 69 // - bools to int/uint (true = 1, false = 0) 70 // - strings to int/uint (base implied by prefix) 71 // - int to bool (true if value != 0) 72 // - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F, 73 // FALSE, false, False. Anything else is an error) 74 // - empty array = empty map and vice versa 75 // - negative numbers to overflowed uint values (base 10) 76 // - slice of maps to a merged map 77 // - single values are converted to slices if required. Each 78 // element is weakly decoded. For example: "4" can become []int{4} 79 // if the target type is an int slice. 80 // 81 WeaklyTypedInput bool 82 83 // Metadata is the struct that will contain extra metadata about 84 // the decoding. If this is nil, then no metadata will be tracked. 85 Metadata *Metadata 86 87 // Result is a pointer to the struct that will contain the decoded 88 // value. 89 Result interface{} 90 91 // The tag name that mapstructure reads for field names. This 92 // defaults to "mapstructure" 93 TagName string 94} 95 96// A Decoder takes a raw interface value and turns it into structured 97// data, keeping track of rich error information along the way in case 98// anything goes wrong. Unlike the basic top-level Decode method, you can 99// more finely control how the Decoder behaves using the DecoderConfig 100// structure. The top-level Decode method is just a convenience that sets 101// up the most basic Decoder. 102type Decoder struct { 103 config *DecoderConfig 104} 105 106// Metadata contains information about decoding a structure that 107// is tedious or difficult to get otherwise. 108type Metadata struct { 109 // Keys are the keys of the structure which were successfully decoded 110 Keys []string 111 112 // Unused is a slice of keys that were found in the raw value but 113 // weren't decoded since there was no matching field in the result interface 114 Unused []string 115} 116 117// Decode takes a map and uses reflection to convert it into the 118// given Go native structure. val must be a pointer to a struct. 119func Decode(m interface{}, rawVal interface{}) error { 120 config := &DecoderConfig{ 121 Metadata: nil, 122 Result: rawVal, 123 } 124 125 decoder, err := NewDecoder(config) 126 if err != nil { 127 return err 128 } 129 130 return decoder.Decode(m) 131} 132 133// WeakDecode is the same as Decode but is shorthand to enable 134// WeaklyTypedInput. See DecoderConfig for more info. 135func WeakDecode(input, output interface{}) error { 136 config := &DecoderConfig{ 137 Metadata: nil, 138 Result: output, 139 WeaklyTypedInput: true, 140 } 141 142 decoder, err := NewDecoder(config) 143 if err != nil { 144 return err 145 } 146 147 return decoder.Decode(input) 148} 149 150// NewDecoder returns a new decoder for the given configuration. Once 151// a decoder has been returned, the same configuration must not be used 152// again. 153func NewDecoder(config *DecoderConfig) (*Decoder, error) { 154 val := reflect.ValueOf(config.Result) 155 if val.Kind() != reflect.Ptr { 156 return nil, errors.New("result must be a pointer") 157 } 158 159 val = val.Elem() 160 if !val.CanAddr() { 161 return nil, errors.New("result must be addressable (a pointer)") 162 } 163 164 if config.Metadata != nil { 165 if config.Metadata.Keys == nil { 166 config.Metadata.Keys = make([]string, 0) 167 } 168 169 if config.Metadata.Unused == nil { 170 config.Metadata.Unused = make([]string, 0) 171 } 172 } 173 174 if config.TagName == "" { 175 config.TagName = "mapstructure" 176 } 177 178 result := &Decoder{ 179 config: config, 180 } 181 182 return result, nil 183} 184 185// Decode decodes the given raw interface to the target pointer specified 186// by the configuration. 187func (d *Decoder) Decode(raw interface{}) error { 188 return d.decode("", raw, reflect.ValueOf(d.config.Result).Elem()) 189} 190 191// Decodes an unknown data type into a specific reflection value. 192func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error { 193 if data == nil { 194 // If the data is nil, then we don't set anything. 195 return nil 196 } 197 198 dataVal := reflect.ValueOf(data) 199 if !dataVal.IsValid() { 200 // If the data value is invalid, then we just set the value 201 // to be the zero value. 202 val.Set(reflect.Zero(val.Type())) 203 return nil 204 } 205 206 if d.config.DecodeHook != nil { 207 // We have a DecodeHook, so let's pre-process the data. 208 var err error 209 data, err = DecodeHookExec( 210 d.config.DecodeHook, 211 dataVal.Type(), val.Type(), data) 212 if err != nil { 213 return fmt.Errorf("error decoding '%s': %s", name, err) 214 } 215 } 216 217 var err error 218 dataKind := getKind(val) 219 switch dataKind { 220 case reflect.Bool: 221 err = d.decodeBool(name, data, val) 222 case reflect.Interface: 223 err = d.decodeBasic(name, data, val) 224 case reflect.String: 225 err = d.decodeString(name, data, val) 226 case reflect.Int: 227 err = d.decodeInt(name, data, val) 228 case reflect.Uint: 229 err = d.decodeUint(name, data, val) 230 case reflect.Float32: 231 err = d.decodeFloat(name, data, val) 232 case reflect.Struct: 233 err = d.decodeStruct(name, data, val) 234 case reflect.Map: 235 err = d.decodeMap(name, data, val) 236 case reflect.Ptr: 237 err = d.decodePtr(name, data, val) 238 case reflect.Slice: 239 err = d.decodeSlice(name, data, val) 240 case reflect.Func: 241 err = d.decodeFunc(name, data, val) 242 default: 243 // If we reached this point then we weren't able to decode it 244 return fmt.Errorf("%s: unsupported type: %s", name, dataKind) 245 } 246 247 // If we reached here, then we successfully decoded SOMETHING, so 248 // mark the key as used if we're tracking metadata. 249 if d.config.Metadata != nil && name != "" { 250 d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) 251 } 252 253 return err 254} 255 256// This decodes a basic type (bool, int, string, etc.) and sets the 257// value to "data" of that type. 258func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { 259 dataVal := reflect.ValueOf(data) 260 if !dataVal.IsValid() { 261 dataVal = reflect.Zero(val.Type()) 262 } 263 264 dataValType := dataVal.Type() 265 if !dataValType.AssignableTo(val.Type()) { 266 return fmt.Errorf( 267 "'%s' expected type '%s', got '%s'", 268 name, val.Type(), dataValType) 269 } 270 271 val.Set(dataVal) 272 return nil 273} 274 275func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { 276 dataVal := reflect.ValueOf(data) 277 dataKind := getKind(dataVal) 278 279 converted := true 280 switch { 281 case dataKind == reflect.String: 282 val.SetString(dataVal.String()) 283 case dataKind == reflect.Bool && d.config.WeaklyTypedInput: 284 if dataVal.Bool() { 285 val.SetString("1") 286 } else { 287 val.SetString("0") 288 } 289 case dataKind == reflect.Int && d.config.WeaklyTypedInput: 290 val.SetString(strconv.FormatInt(dataVal.Int(), 10)) 291 case dataKind == reflect.Uint && d.config.WeaklyTypedInput: 292 val.SetString(strconv.FormatUint(dataVal.Uint(), 10)) 293 case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: 294 val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64)) 295 case dataKind == reflect.Slice && d.config.WeaklyTypedInput: 296 dataType := dataVal.Type() 297 elemKind := dataType.Elem().Kind() 298 switch { 299 case elemKind == reflect.Uint8: 300 val.SetString(string(dataVal.Interface().([]uint8))) 301 default: 302 converted = false 303 } 304 default: 305 converted = false 306 } 307 308 if !converted { 309 return fmt.Errorf( 310 "'%s' expected type '%s', got unconvertible type '%s'", 311 name, val.Type(), dataVal.Type()) 312 } 313 314 return nil 315} 316 317func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { 318 dataVal := reflect.ValueOf(data) 319 dataKind := getKind(dataVal) 320 dataType := dataVal.Type() 321 322 switch { 323 case dataKind == reflect.Int: 324 val.SetInt(dataVal.Int()) 325 case dataKind == reflect.Uint: 326 val.SetInt(int64(dataVal.Uint())) 327 case dataKind == reflect.Float32: 328 val.SetInt(int64(dataVal.Float())) 329 case dataKind == reflect.Bool && d.config.WeaklyTypedInput: 330 if dataVal.Bool() { 331 val.SetInt(1) 332 } else { 333 val.SetInt(0) 334 } 335 case dataKind == reflect.String && d.config.WeaklyTypedInput: 336 i, err := strconv.ParseInt(dataVal.String(), 0, val.Type().Bits()) 337 if err == nil { 338 val.SetInt(i) 339 } else { 340 return fmt.Errorf("cannot parse '%s' as int: %s", name, err) 341 } 342 case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": 343 jn := data.(json.Number) 344 i, err := jn.Int64() 345 if err != nil { 346 return fmt.Errorf( 347 "error decoding json.Number into %s: %s", name, err) 348 } 349 val.SetInt(i) 350 default: 351 return fmt.Errorf( 352 "'%s' expected type '%s', got unconvertible type '%s'", 353 name, val.Type(), dataVal.Type()) 354 } 355 356 return nil 357} 358 359func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { 360 dataVal := reflect.ValueOf(data) 361 dataKind := getKind(dataVal) 362 363 switch { 364 case dataKind == reflect.Int: 365 i := dataVal.Int() 366 if i < 0 && !d.config.WeaklyTypedInput { 367 return fmt.Errorf("cannot parse '%s', %d overflows uint", 368 name, i) 369 } 370 val.SetUint(uint64(i)) 371 case dataKind == reflect.Uint: 372 val.SetUint(dataVal.Uint()) 373 case dataKind == reflect.Float32: 374 f := dataVal.Float() 375 if f < 0 && !d.config.WeaklyTypedInput { 376 return fmt.Errorf("cannot parse '%s', %f overflows uint", 377 name, f) 378 } 379 val.SetUint(uint64(f)) 380 case dataKind == reflect.Bool && d.config.WeaklyTypedInput: 381 if dataVal.Bool() { 382 val.SetUint(1) 383 } else { 384 val.SetUint(0) 385 } 386 case dataKind == reflect.String && d.config.WeaklyTypedInput: 387 i, err := strconv.ParseUint(dataVal.String(), 0, val.Type().Bits()) 388 if err == nil { 389 val.SetUint(i) 390 } else { 391 return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) 392 } 393 default: 394 return fmt.Errorf( 395 "'%s' expected type '%s', got unconvertible type '%s'", 396 name, val.Type(), dataVal.Type()) 397 } 398 399 return nil 400} 401 402func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { 403 dataVal := reflect.ValueOf(data) 404 dataKind := getKind(dataVal) 405 406 switch { 407 case dataKind == reflect.Bool: 408 val.SetBool(dataVal.Bool()) 409 case dataKind == reflect.Int && d.config.WeaklyTypedInput: 410 val.SetBool(dataVal.Int() != 0) 411 case dataKind == reflect.Uint && d.config.WeaklyTypedInput: 412 val.SetBool(dataVal.Uint() != 0) 413 case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: 414 val.SetBool(dataVal.Float() != 0) 415 case dataKind == reflect.String && d.config.WeaklyTypedInput: 416 b, err := strconv.ParseBool(dataVal.String()) 417 if err == nil { 418 val.SetBool(b) 419 } else if dataVal.String() == "" { 420 val.SetBool(false) 421 } else { 422 return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) 423 } 424 default: 425 return fmt.Errorf( 426 "'%s' expected type '%s', got unconvertible type '%s'", 427 name, val.Type(), dataVal.Type()) 428 } 429 430 return nil 431} 432 433func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { 434 dataVal := reflect.ValueOf(data) 435 dataKind := getKind(dataVal) 436 dataType := dataVal.Type() 437 438 switch { 439 case dataKind == reflect.Int: 440 val.SetFloat(float64(dataVal.Int())) 441 case dataKind == reflect.Uint: 442 val.SetFloat(float64(dataVal.Uint())) 443 case dataKind == reflect.Float32: 444 val.SetFloat(dataVal.Float()) 445 case dataKind == reflect.Bool && d.config.WeaklyTypedInput: 446 if dataVal.Bool() { 447 val.SetFloat(1) 448 } else { 449 val.SetFloat(0) 450 } 451 case dataKind == reflect.String && d.config.WeaklyTypedInput: 452 f, err := strconv.ParseFloat(dataVal.String(), val.Type().Bits()) 453 if err == nil { 454 val.SetFloat(f) 455 } else { 456 return fmt.Errorf("cannot parse '%s' as float: %s", name, err) 457 } 458 case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": 459 jn := data.(json.Number) 460 i, err := jn.Float64() 461 if err != nil { 462 return fmt.Errorf( 463 "error decoding json.Number into %s: %s", name, err) 464 } 465 val.SetFloat(i) 466 default: 467 return fmt.Errorf( 468 "'%s' expected type '%s', got unconvertible type '%s'", 469 name, val.Type(), dataVal.Type()) 470 } 471 472 return nil 473} 474 475func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { 476 valType := val.Type() 477 valKeyType := valType.Key() 478 valElemType := valType.Elem() 479 480 // By default we overwrite keys in the current map 481 valMap := val 482 483 // If the map is nil or we're purposely zeroing fields, make a new map 484 if valMap.IsNil() || d.config.ZeroFields { 485 // Make a new map to hold our result 486 mapType := reflect.MapOf(valKeyType, valElemType) 487 valMap = reflect.MakeMap(mapType) 488 } 489 490 // Check input type 491 dataVal := reflect.Indirect(reflect.ValueOf(data)) 492 if dataVal.Kind() != reflect.Map { 493 // In weak mode, we accept a slice of maps as an input... 494 if d.config.WeaklyTypedInput { 495 switch dataVal.Kind() { 496 case reflect.Array, reflect.Slice: 497 // Special case for BC reasons (covered by tests) 498 if dataVal.Len() == 0 { 499 val.Set(valMap) 500 return nil 501 } 502 503 for i := 0; i < dataVal.Len(); i++ { 504 err := d.decode( 505 fmt.Sprintf("%s[%d]", name, i), 506 dataVal.Index(i).Interface(), val) 507 if err != nil { 508 return err 509 } 510 } 511 512 return nil 513 } 514 } 515 516 return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) 517 } 518 519 // Accumulate errors 520 errors := make([]string, 0) 521 522 for _, k := range dataVal.MapKeys() { 523 fieldName := fmt.Sprintf("%s[%s]", name, k) 524 525 // First decode the key into the proper type 526 currentKey := reflect.Indirect(reflect.New(valKeyType)) 527 if err := d.decode(fieldName, k.Interface(), currentKey); err != nil { 528 errors = appendErrors(errors, err) 529 continue 530 } 531 532 // Next decode the data into the proper type 533 v := dataVal.MapIndex(k).Interface() 534 currentVal := reflect.Indirect(reflect.New(valElemType)) 535 if err := d.decode(fieldName, v, currentVal); err != nil { 536 errors = appendErrors(errors, err) 537 continue 538 } 539 540 valMap.SetMapIndex(currentKey, currentVal) 541 } 542 543 // Set the built up map to the value 544 val.Set(valMap) 545 546 // If we had errors, return those 547 if len(errors) > 0 { 548 return &Error{errors} 549 } 550 551 return nil 552} 553 554func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) error { 555 // Create an element of the concrete (non pointer) type and decode 556 // into that. Then set the value of the pointer to this type. 557 valType := val.Type() 558 valElemType := valType.Elem() 559 560 realVal := val 561 if realVal.IsNil() || d.config.ZeroFields { 562 realVal = reflect.New(valElemType) 563 } 564 565 if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { 566 return err 567 } 568 569 val.Set(realVal) 570 return nil 571} 572 573func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error { 574 // Create an element of the concrete (non pointer) type and decode 575 // into that. Then set the value of the pointer to this type. 576 dataVal := reflect.Indirect(reflect.ValueOf(data)) 577 if val.Type() != dataVal.Type() { 578 return fmt.Errorf( 579 "'%s' expected type '%s', got unconvertible type '%s'", 580 name, val.Type(), dataVal.Type()) 581 } 582 val.Set(dataVal) 583 return nil 584} 585 586func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { 587 dataVal := reflect.Indirect(reflect.ValueOf(data)) 588 dataValKind := dataVal.Kind() 589 valType := val.Type() 590 valElemType := valType.Elem() 591 sliceType := reflect.SliceOf(valElemType) 592 593 valSlice := val 594 if valSlice.IsNil() || d.config.ZeroFields { 595 // Check input type 596 if dataValKind != reflect.Array && dataValKind != reflect.Slice { 597 if d.config.WeaklyTypedInput { 598 switch { 599 // Empty maps turn into empty slices 600 case dataValKind == reflect.Map: 601 if dataVal.Len() == 0 { 602 val.Set(reflect.MakeSlice(sliceType, 0, 0)) 603 return nil 604 } 605 606 // All other types we try to convert to the slice type 607 // and "lift" it into it. i.e. a string becomes a string slice. 608 default: 609 // Just re-try this function with data as a slice. 610 return d.decodeSlice(name, []interface{}{data}, val) 611 } 612 } 613 614 return fmt.Errorf( 615 "'%s': source data must be an array or slice, got %s", name, dataValKind) 616 617 } 618 619 // Make a new slice to hold our result, same size as the original data. 620 valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) 621 } 622 623 // Accumulate any errors 624 errors := make([]string, 0) 625 626 for i := 0; i < dataVal.Len(); i++ { 627 currentData := dataVal.Index(i).Interface() 628 for valSlice.Len() <= i { 629 valSlice = reflect.Append(valSlice, reflect.Zero(valElemType)) 630 } 631 currentField := valSlice.Index(i) 632 633 fieldName := fmt.Sprintf("%s[%d]", name, i) 634 if err := d.decode(fieldName, currentData, currentField); err != nil { 635 errors = appendErrors(errors, err) 636 } 637 } 638 639 // Finally, set the value to the slice we built up 640 val.Set(valSlice) 641 642 // If there were errors, we return those 643 if len(errors) > 0 { 644 return &Error{errors} 645 } 646 647 return nil 648} 649 650func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { 651 dataVal := reflect.Indirect(reflect.ValueOf(data)) 652 653 // If the type of the value to write to and the data match directly, 654 // then we just set it directly instead of recursing into the structure. 655 if dataVal.Type() == val.Type() { 656 val.Set(dataVal) 657 return nil 658 } 659 660 dataValKind := dataVal.Kind() 661 if dataValKind != reflect.Map { 662 return fmt.Errorf("'%s' expected a map, got '%s'", name, dataValKind) 663 } 664 665 dataValType := dataVal.Type() 666 if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { 667 return fmt.Errorf( 668 "'%s' needs a map with string keys, has '%s' keys", 669 name, dataValType.Key().Kind()) 670 } 671 672 dataValKeys := make(map[reflect.Value]struct{}) 673 dataValKeysUnused := make(map[interface{}]struct{}) 674 for _, dataValKey := range dataVal.MapKeys() { 675 dataValKeys[dataValKey] = struct{}{} 676 dataValKeysUnused[dataValKey.Interface()] = struct{}{} 677 } 678 679 errors := make([]string, 0) 680 681 // This slice will keep track of all the structs we'll be decoding. 682 // There can be more than one struct if there are embedded structs 683 // that are squashed. 684 structs := make([]reflect.Value, 1, 5) 685 structs[0] = val 686 687 // Compile the list of all the fields that we're going to be decoding 688 // from all the structs. 689 fields := make(map[*reflect.StructField]reflect.Value) 690 for len(structs) > 0 { 691 structVal := structs[0] 692 structs = structs[1:] 693 694 structType := structVal.Type() 695 696 for i := 0; i < structType.NumField(); i++ { 697 fieldType := structType.Field(i) 698 fieldKind := fieldType.Type.Kind() 699 700 // If "squash" is specified in the tag, we squash the field down. 701 squash := false 702 tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") 703 for _, tag := range tagParts[1:] { 704 if tag == "squash" { 705 squash = true 706 break 707 } 708 } 709 710 if squash { 711 if fieldKind != reflect.Struct { 712 errors = appendErrors(errors, 713 fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldKind)) 714 } else { 715 structs = append(structs, val.FieldByName(fieldType.Name)) 716 } 717 continue 718 } 719 720 // Normal struct field, store it away 721 fields[&fieldType] = structVal.Field(i) 722 } 723 } 724 725 for fieldType, field := range fields { 726 fieldName := fieldType.Name 727 728 tagValue := fieldType.Tag.Get(d.config.TagName) 729 tagValue = strings.SplitN(tagValue, ",", 2)[0] 730 if tagValue != "" { 731 fieldName = tagValue 732 } 733 734 rawMapKey := reflect.ValueOf(fieldName) 735 rawMapVal := dataVal.MapIndex(rawMapKey) 736 if !rawMapVal.IsValid() { 737 // Do a slower search by iterating over each key and 738 // doing case-insensitive search. 739 for dataValKey := range dataValKeys { 740 mK, ok := dataValKey.Interface().(string) 741 if !ok { 742 // Not a string key 743 continue 744 } 745 746 if strings.EqualFold(mK, fieldName) { 747 rawMapKey = dataValKey 748 rawMapVal = dataVal.MapIndex(dataValKey) 749 break 750 } 751 } 752 753 if !rawMapVal.IsValid() { 754 // There was no matching key in the map for the value in 755 // the struct. Just ignore. 756 continue 757 } 758 } 759 760 // Delete the key we're using from the unused map so we stop tracking 761 delete(dataValKeysUnused, rawMapKey.Interface()) 762 763 if !field.IsValid() { 764 // This should never happen 765 panic("field is not valid") 766 } 767 768 // If we can't set the field, then it is unexported or something, 769 // and we just continue onwards. 770 if !field.CanSet() { 771 continue 772 } 773 774 // If the name is empty string, then we're at the root, and we 775 // don't dot-join the fields. 776 if name != "" { 777 fieldName = fmt.Sprintf("%s.%s", name, fieldName) 778 } 779 780 if err := d.decode(fieldName, rawMapVal.Interface(), field); err != nil { 781 errors = appendErrors(errors, err) 782 } 783 } 784 785 if d.config.ErrorUnused && len(dataValKeysUnused) > 0 { 786 keys := make([]string, 0, len(dataValKeysUnused)) 787 for rawKey := range dataValKeysUnused { 788 keys = append(keys, rawKey.(string)) 789 } 790 sort.Strings(keys) 791 792 err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) 793 errors = appendErrors(errors, err) 794 } 795 796 if len(errors) > 0 { 797 return &Error{errors} 798 } 799 800 // Add the unused keys to the list of unused keys if we're tracking metadata 801 if d.config.Metadata != nil { 802 for rawKey := range dataValKeysUnused { 803 key := rawKey.(string) 804 if name != "" { 805 key = fmt.Sprintf("%s.%s", name, key) 806 } 807 808 d.config.Metadata.Unused = append(d.config.Metadata.Unused, key) 809 } 810 } 811 812 return nil 813} 814 815func getKind(val reflect.Value) reflect.Kind { 816 kind := val.Kind() 817 818 switch { 819 case kind >= reflect.Int && kind <= reflect.Int64: 820 return reflect.Int 821 case kind >= reflect.Uint && kind <= reflect.Uint64: 822 return reflect.Uint 823 case kind >= reflect.Float32 && kind <= reflect.Float64: 824 return reflect.Float32 825 default: 826 return kind 827 } 828} 829