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