@@ -160,12 +160,13 @@ package mapstructure
160
160
161
161
import (
162
162
"encoding/json"
163
- "errors"
164
163
"fmt"
165
164
"reflect"
166
165
"sort"
167
166
"strconv"
168
167
"strings"
168
+
169
+ "github.com/go-viper/mapstructure/v2/internal/errors"
169
170
)
170
171
171
172
// DecodeHookFunc is the callback function that can be used for
@@ -414,7 +415,15 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) {
414
415
// Decode decodes the given raw interface to the target pointer specified
415
416
// by the configuration.
416
417
func (d * Decoder ) Decode (input interface {}) error {
417
- return d .decode ("" , input , reflect .ValueOf (d .config .Result ).Elem ())
418
+ err := d .decode ("" , input , reflect .ValueOf (d .config .Result ).Elem ())
419
+
420
+ // Retain some of the original behavior when multiple errors ocurr
421
+ var joinedErr interface { Unwrap () []error }
422
+ if errors .As (err , & joinedErr ) {
423
+ return fmt .Errorf ("decoding failed due to the following error(s):\n \n %w" , err )
424
+ }
425
+
426
+ return err
418
427
}
419
428
420
429
// Decodes an unknown data type into a specific reflection value.
@@ -881,7 +890,7 @@ func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val refle
881
890
valElemType := valType .Elem ()
882
891
883
892
// Accumulate errors
884
- errors := make ([] string , 0 )
893
+ var errs [] error
885
894
886
895
// If the input data is empty, then we just match what the input data is.
887
896
if dataVal .Len () == 0 {
@@ -903,15 +912,15 @@ func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val refle
903
912
// First decode the key into the proper type
904
913
currentKey := reflect .Indirect (reflect .New (valKeyType ))
905
914
if err := d .decode (fieldName , k .Interface (), currentKey ); err != nil {
906
- errors = appendErrors ( errors , err )
915
+ errs = append ( errs , err )
907
916
continue
908
917
}
909
918
910
919
// Next decode the data into the proper type
911
920
v := dataVal .MapIndex (k ).Interface ()
912
921
currentVal := reflect .Indirect (reflect .New (valElemType ))
913
922
if err := d .decode (fieldName , v , currentVal ); err != nil {
914
- errors = appendErrors ( errors , err )
923
+ errs = append ( errs , err )
915
924
continue
916
925
}
917
926
@@ -921,12 +930,7 @@ func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val refle
921
930
// Set the built up map to the value
922
931
val .Set (valMap )
923
932
924
- // If we had errors, return those
925
- if len (errors ) > 0 {
926
- return & joinedError {errors }
927
- }
928
-
929
- return nil
933
+ return errors .Join (errs ... )
930
934
}
931
935
932
936
func (d * Decoder ) decodeMapFromStruct (name string , dataVal reflect.Value , val reflect.Value , valMap reflect.Value ) error {
@@ -1164,7 +1168,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
1164
1168
}
1165
1169
1166
1170
// Accumulate any errors
1167
- errors := make ([] string , 0 )
1171
+ var errs [] error
1168
1172
1169
1173
for i := 0 ; i < dataVal .Len (); i ++ {
1170
1174
currentData := dataVal .Index (i ).Interface ()
@@ -1175,19 +1179,14 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
1175
1179
1176
1180
fieldName := name + "[" + strconv .Itoa (i ) + "]"
1177
1181
if err := d .decode (fieldName , currentData , currentField ); err != nil {
1178
- errors = appendErrors ( errors , err )
1182
+ errs = append ( errs , err )
1179
1183
}
1180
1184
}
1181
1185
1182
1186
// Finally, set the value to the slice we built up
1183
1187
val .Set (valSlice )
1184
1188
1185
- // If there were errors, we return those
1186
- if len (errors ) > 0 {
1187
- return & joinedError {errors }
1188
- }
1189
-
1190
- return nil
1189
+ return errors .Join (errs ... )
1191
1190
}
1192
1191
1193
1192
func (d * Decoder ) decodeArray (name string , data interface {}, val reflect.Value ) error {
@@ -1233,27 +1232,22 @@ func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value)
1233
1232
}
1234
1233
1235
1234
// Accumulate any errors
1236
- errors := make ([] string , 0 )
1235
+ var errs [] error
1237
1236
1238
1237
for i := 0 ; i < dataVal .Len (); i ++ {
1239
1238
currentData := dataVal .Index (i ).Interface ()
1240
1239
currentField := valArray .Index (i )
1241
1240
1242
1241
fieldName := name + "[" + strconv .Itoa (i ) + "]"
1243
1242
if err := d .decode (fieldName , currentData , currentField ); err != nil {
1244
- errors = appendErrors ( errors , err )
1243
+ errs = append ( errs , err )
1245
1244
}
1246
1245
}
1247
1246
1248
1247
// Finally, set the value to the array we built up
1249
1248
val .Set (valArray )
1250
1249
1251
- // If there were errors, we return those
1252
- if len (errors ) > 0 {
1253
- return & joinedError {errors }
1254
- }
1255
-
1256
- return nil
1250
+ return errors .Join (errs ... )
1257
1251
}
1258
1252
1259
1253
func (d * Decoder ) decodeStruct (name string , data interface {}, val reflect.Value ) error {
@@ -1315,7 +1309,8 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
1315
1309
}
1316
1310
1317
1311
targetValKeysUnused := make (map [interface {}]struct {})
1318
- errors := make ([]string , 0 )
1312
+
1313
+ var errs []error
1319
1314
1320
1315
// This slice will keep track of all the structs we'll be decoding.
1321
1316
// There can be more than one struct if there are embedded structs
@@ -1369,8 +1364,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
1369
1364
1370
1365
if squash {
1371
1366
if fieldVal .Kind () != reflect .Struct {
1372
- errors = appendErrors (errors ,
1373
- fmt .Errorf ("%s: unsupported type for squash: %s" , fieldType .Name , fieldVal .Kind ()))
1367
+ errs = append (errs , fmt .Errorf ("%s: unsupported type for squash: %s" , fieldType .Name , fieldVal .Kind ()))
1374
1368
} else {
1375
1369
structs = append (structs , fieldVal )
1376
1370
}
@@ -1449,7 +1443,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
1449
1443
}
1450
1444
1451
1445
if err := d .decode (fieldName , rawMapVal .Interface (), fieldValue ); err != nil {
1452
- errors = appendErrors ( errors , err )
1446
+ errs = append ( errs , err )
1453
1447
}
1454
1448
}
1455
1449
@@ -1464,7 +1458,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
1464
1458
1465
1459
// Decode it as-if we were just decoding this map onto our map.
1466
1460
if err := d .decodeMap (name , remain , remainField .val ); err != nil {
1467
- errors = appendErrors ( errors , err )
1461
+ errs = append ( errs , err )
1468
1462
}
1469
1463
1470
1464
// Set the map to nil so we have none so that the next check will
@@ -1480,7 +1474,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
1480
1474
sort .Strings (keys )
1481
1475
1482
1476
err := fmt .Errorf ("'%s' has invalid keys: %s" , name , strings .Join (keys , ", " ))
1483
- errors = appendErrors ( errors , err )
1477
+ errs = append ( errs , err )
1484
1478
}
1485
1479
1486
1480
if d .config .ErrorUnset && len (targetValKeysUnused ) > 0 {
@@ -1491,11 +1485,11 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
1491
1485
sort .Strings (keys )
1492
1486
1493
1487
err := fmt .Errorf ("'%s' has unset fields: %s" , name , strings .Join (keys , ", " ))
1494
- errors = appendErrors ( errors , err )
1488
+ errs = append ( errs , err )
1495
1489
}
1496
1490
1497
- if len ( errors ) > 0 {
1498
- return & joinedError { errors }
1491
+ if err := errors . Join ( errs ... ); err != nil {
1492
+ return err
1499
1493
}
1500
1494
1501
1495
// Add the unused keys to the list of unused keys if we're tracking metadata
0 commit comments