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