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