@@ -442,22 +442,15 @@ func (d *Decoder) Decode(input interface{}) error {
442
442
return err
443
443
}
444
444
445
- // A comparison input == nil will fail if input is a typed nil.
446
- // This function converts a typed nil to an actual, untyped nil.
447
- func toRealNil (input interface {}) interface {} {
445
+ // isNil returns true if the input is nil or a typed nil pointer.
446
+ func isNil (input interface {}) bool {
448
447
if input == nil {
449
- return nil
448
+ return true
450
449
}
451
450
val := reflect .ValueOf (input )
452
451
k := val .Kind ()
453
- if (k == reflect .Ptr ||
454
- k == reflect .Interface ||
455
- k == reflect .Map ||
456
- k == reflect .Slice ||
457
- k == reflect .Array ) && val .IsNil () {
458
- return nil
459
- }
460
- return input
452
+ return (k == reflect .Ptr ||
453
+ /*k == reflect.Interface || k == reflect.Map || k == reflect.Slice*/ false ) && val .IsNil ()
461
454
}
462
455
463
456
// Decodes an unknown data type into a specific reflection value.
@@ -467,8 +460,14 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
467
460
outputKind = getKind (outVal )
468
461
decodeNil = d .config .DecodeNil && d .cachedDecodeHook != nil
469
462
)
470
- input = toRealNil (input )
471
- if input == nil || ! inputVal .IsValid () {
463
+ if input != nil {
464
+ // We need to check here if input is a typed nil. Typed nils won't
465
+ // match the "input == nil" below so we check that here.
466
+ if inputVal .Kind () == reflect .Ptr && inputVal .IsNil () {
467
+ input = nil
468
+ }
469
+ }
470
+ if input == nil {
472
471
// If the data is nil, then we don't set anything, unless ZeroFields is set
473
472
// to true.
474
473
if d .config .ZeroFields {
@@ -482,29 +481,41 @@ func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) e
482
481
return nil
483
482
}
484
483
}
484
+ if ! inputVal .IsValid () {
485
+ if ! decodeNil {
486
+ // If the input value is invalid, then we just set the value
487
+ // to be the zero value.
488
+ outVal .Set (reflect .Zero (outVal .Type ()))
489
+ if d .config .Metadata != nil && name != "" {
490
+ d .config .Metadata .Keys = append (d .config .Metadata .Keys , name )
491
+ }
492
+ return nil
493
+ }
494
+ // Hooks need a valid inputVal, so reset it to zero value of outVal type.
495
+ switch outputKind {
496
+ case reflect .Struct , reflect .Map :
497
+ // create empty map
498
+ var mapVal map [string ]interface {}
499
+ inputVal = reflect .ValueOf (mapVal )
500
+ // inputVal = reflect.MakeMap(reflect.TypeOf(mapVal))
501
+ case reflect .Slice , reflect .Array :
502
+ // create nil slice
503
+ var sliceVal []interface {}
504
+ inputVal = reflect .ValueOf (sliceVal )
505
+ default :
506
+ inputVal = reflect .Zero (outVal .Type ())
507
+ }
508
+ }
485
509
486
510
if d .cachedDecodeHook != nil {
487
511
// We have a DecodeHook, so let's pre-process the input.
488
- if ! inputVal .IsValid () {
489
- // Hooks need a valid inputVal, so reset it to zero value of outVal type.
490
- switch outputKind {
491
- case reflect .Struct , reflect .Map :
492
- var mapVal map [string ]interface {}
493
- inputVal = reflect .ValueOf (mapVal )
494
- case reflect .Slice , reflect .Array :
495
- var sliceVal []interface {}
496
- inputVal = reflect .ValueOf (sliceVal )
497
- default :
498
- inputVal = reflect .Zero (outVal .Type ())
499
- }
500
- }
501
512
var err error
502
513
input , err = d .cachedDecodeHook (inputVal , outVal )
503
514
if err != nil {
504
515
return fmt .Errorf ("error decoding '%s': %w" , name , err )
505
516
}
506
517
}
507
- if toRealNil (input ) == nil {
518
+ if isNil (input ) {
508
519
return nil
509
520
}
510
521
@@ -789,8 +800,8 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e
789
800
}
790
801
default :
791
802
return fmt .Errorf (
792
- "'%s' expected type '%s', got unconvertible type '%s ', value: '%v'" ,
793
- name , val . Type () , dataVal . Type () , data )
803
+ "'%s' expected type '%s', got unconvertible type '%#v ', value: '%# v'" ,
804
+ name , val , dataVal , data )
794
805
}
795
806
796
807
return nil
0 commit comments