Skip to content

Commit 92d7689

Browse files
authored
Fix configreader struct nil handling (#106)
1 parent 752e76c commit 92d7689

File tree

3 files changed

+271
-56
lines changed

3 files changed

+271
-56
lines changed

pkg/lib/configreader/reader.go

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,17 @@ type StructFieldValidation struct {
7979
type StructValidation struct {
8080
StructFieldValidations []*StructFieldValidation
8181
Required bool
82-
AllowNull bool
83-
DefualtNil bool // If this struct is nested and it's key is not defined, set it to nil instead of defaults or erroring (e.g. if any subfields are required)
82+
AllowExplicitNull bool
83+
DefaultNil bool // If this struct is nested and its key is not defined, set it to nil instead of defaults or erroring (e.g. if any subfields are required)
8484
ShortCircuit bool
8585
AllowExtraFields bool
8686
}
8787

8888
type StructListValidation struct {
89-
StructValidation *StructValidation
90-
Required bool
91-
AllowNull bool
92-
ShortCircuit bool
89+
StructValidation *StructValidation
90+
Required bool
91+
AllowExplicitNull bool
92+
ShortCircuit bool
9393
}
9494

9595
type InterfaceStructValidation struct {
@@ -99,7 +99,7 @@ type InterfaceStructValidation struct {
9999
ParsedInterfaceStructTypes map[interface{}]*InterfaceStructType // must specify Parser if using this
100100
Parser func(string) (interface{}, error)
101101
Required bool
102-
AllowNull bool
102+
AllowExplicitNull bool
103103
ShortCircuit bool
104104
AllowExtraFields bool
105105
}
@@ -112,7 +112,7 @@ type InterfaceStructType struct {
112112
type InterfaceStructListValidation struct {
113113
InterfaceStructValidation *InterfaceStructValidation
114114
Required bool
115-
AllowNull bool
115+
AllowExplicitNull bool
116116
ShortCircuit bool
117117
}
118118

@@ -122,9 +122,10 @@ func Struct(dest interface{}, inter interface{}, v *StructValidation) []error {
122122
var ok bool
123123

124124
if inter == nil {
125-
if !v.AllowNull {
125+
if !v.AllowExplicitNull {
126126
return []error{ErrorCannotBeNull()}
127127
}
128+
return nil
128129
}
129130

130131
interMap, ok := cast.InterfaceToStrInterfaceMap(inter)
@@ -271,14 +272,17 @@ func Struct(dest interface{}, inter interface{}, v *StructValidation) []error {
271272
interMapVal, ok := ReadInterfaceMapValue(key, interMap)
272273
if !ok && validation.Required {
273274
err = errors.Wrap(ErrorMustBeDefined(), key)
274-
} else if !ok && validation.DefualtNil {
275+
} else if !ok && validation.DefaultNil {
275276
val = nil
276277
} else {
277278
if !ok {
278-
interMapVal = make(map[string]interface{}) // Distinguish between null and not defined
279+
interMapVal = make(map[string]interface{}) // Here validation.DefaultNil == false, so create an empty map to hold the nested default values
279280
}
280281
val = reflect.New(nestedType.Elem()).Interface()
281282
errs = Struct(val, interMapVal, &validation)
283+
if interMapVal == nil {
284+
val = nil // If the object was nil, set val to nil rather than a pointer to the initialized zero value
285+
}
282286
errs = errors.WrapMultiple(errs, key)
283287
}
284288

@@ -358,7 +362,7 @@ func Struct(dest interface{}, inter interface{}, v *StructValidation) []error {
358362

359363
func StructList(dest interface{}, inter interface{}, v *StructListValidation) (interface{}, []error) {
360364
if inter == nil {
361-
if !v.AllowNull {
365+
if !v.AllowExplicitNull {
362366
return nil, []error{ErrorCannotBeNull()}
363367
}
364368
return nil, nil
@@ -380,6 +384,9 @@ func StructList(dest interface{}, inter interface{}, v *StructListValidation) (i
380384
}
381385
continue
382386
}
387+
if interItem == nil {
388+
val = nil // If the object was nil, set val to nil rather than a pointer to the initialized zero value
389+
}
383390
dest = appendVal(dest, val)
384391
}
385392

@@ -388,7 +395,7 @@ func StructList(dest interface{}, inter interface{}, v *StructListValidation) (i
388395

389396
func InterfaceStruct(inter interface{}, v *InterfaceStructValidation) (interface{}, []error) {
390397
if inter == nil {
391-
if !v.AllowNull {
398+
if !v.AllowExplicitNull {
392399
return nil, []error{ErrorCannotBeNull()}
393400
}
394401
return nil, nil
@@ -457,7 +464,7 @@ func InterfaceStruct(inter interface{}, v *InterfaceStructValidation) (interface
457464
structValidation := &StructValidation{
458465
StructFieldValidations: append(structType.StructFieldValidations, typeFieldValidation),
459466
Required: v.Required,
460-
AllowNull: v.AllowNull,
467+
AllowExplicitNull: v.AllowExplicitNull,
461468
ShortCircuit: v.ShortCircuit,
462469
AllowExtraFields: v.AllowExtraFields,
463470
}
@@ -467,7 +474,7 @@ func InterfaceStruct(inter interface{}, v *InterfaceStructValidation) (interface
467474

468475
func InterfaceStructList(dest interface{}, inter interface{}, v *InterfaceStructListValidation) (interface{}, []error) {
469476
if inter == nil {
470-
if !v.AllowNull {
477+
if !v.AllowExplicitNull {
471478
return nil, []error{ErrorCannotBeNull()}
472479
}
473480
return nil, nil
@@ -595,11 +602,11 @@ func prompt(opts *PromptOptions) string {
595602
prompt := opts.Prompt
596603

597604
if opts.defaultStr != "" {
598-
defualtStr := opts.defaultStr
605+
defaultStr := opts.defaultStr
599606
if opts.MaskDefault {
600-
defualtStr = s.MaskString(defualtStr, 4)
607+
defaultStr = s.MaskString(defaultStr, 4)
601608
}
602-
prompt = fmt.Sprintf("%s [%s]", opts.Prompt, defualtStr)
609+
prompt = fmt.Sprintf("%s [%s]", opts.Prompt, defaultStr)
603610
}
604611

605612
val, err := ui.Ask(prompt, &input.Options{
@@ -700,13 +707,13 @@ func appendVal(slice interface{}, val interface{}) interface{} {
700707
func setField(val interface{}, destStruct interface{}, fieldName string) error {
701708
v := reflect.ValueOf(destStruct).Elem().FieldByName(fieldName)
702709
if !v.IsValid() || !v.CanSet() {
703-
debug.Pp(val)
704-
debug.Pp(destStruct)
710+
debug.Ppg(val)
711+
debug.Ppg(destStruct)
705712
return errors.Wrap(ErrorCannotSetStructField(), fieldName)
706713
}
707714
if !reflect.ValueOf(val).Type().AssignableTo(v.Type()) {
708-
debug.Pp(val)
709-
debug.Pp(destStruct)
715+
debug.Ppg(val)
716+
debug.Ppg(destStruct)
710717
return errors.Wrap(ErrorCannotSetStructField(), fieldName)
711718
}
712719
v.Set(reflect.ValueOf(val))
@@ -717,8 +724,8 @@ func setField(val interface{}, destStruct interface{}, fieldName string) error {
717724
func setFirstField(val interface{}, destStruct interface{}) error {
718725
v := reflect.ValueOf(destStruct).Elem().FieldByIndex([]int{0})
719726
if !v.IsValid() || !v.CanSet() {
720-
debug.Pp(val)
721-
debug.Pp(destStruct)
727+
debug.Ppg(val)
728+
debug.Ppg(destStruct)
722729
return errors.Wrap(ErrorCannotSetStructField(), "first field")
723730
}
724731
v.Set(reflect.ValueOf(val))
@@ -729,7 +736,7 @@ func setFirstField(val interface{}, destStruct interface{}) error {
729736
func setFieldNil(destStruct interface{}, fieldName string) error {
730737
v := reflect.ValueOf(destStruct).Elem().FieldByName(fieldName)
731738
if !v.IsValid() || !v.CanSet() {
732-
debug.Pp(destStruct)
739+
debug.Ppg(destStruct)
733740
return errors.Wrap(ErrorCannotSetStructField(), fieldName)
734741
}
735742
v.Set(reflect.Zero(v.Type()))

0 commit comments

Comments
 (0)