Skip to content

Commit

Permalink
recursive finding of fields in embedded structs
Browse files Browse the repository at this point in the history
  • Loading branch information
FZambia committed Sep 21, 2024
1 parent af80e46 commit d22cc1c
Showing 1 changed file with 25 additions and 22 deletions.
47 changes: 25 additions & 22 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,29 @@ func extendKnownEnvVars(knownEnvVars map[string]struct{}, varInfo []envconfig.Va
}
}

// findValidKeys recursively finds valid keys in a struct, including embedded structs
func findValidKeys(typ reflect.Type, validKeys map[string]reflect.StructField) {
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
tag := field.Tag.Get("mapstructure")

if tag != "" && tag != ",squash" {
// Normal field, add it to validKeys.
validKeys[tag] = field
} else if field.Anonymous && strings.Contains(tag, "squash") {
// Handle embedded fields with "squash".
embeddedType := field.Type
if embeddedType.Kind() == reflect.Ptr {
embeddedType = embeddedType.Elem()
}
if embeddedType.Kind() == reflect.Struct {
// Recursively process the embedded struct
findValidKeys(embeddedType, validKeys)
}
}
}
}

func findUnknownKeys(data map[string]interface{}, configStruct interface{}, parentKey string) []string {
var unknownKeys []string
val := reflect.ValueOf(configStruct)
Expand All @@ -278,29 +301,9 @@ func findUnknownKeys(data map[string]interface{}, configStruct interface{}, pare
}
typ := val.Type()

// Build a set of valid keys from the struct's mapstructure tags, including embedded structs
// Build a set of valid keys from the struct's mapstructure tags, including embedded structs.
validKeys := make(map[string]reflect.StructField)
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
tag := field.Tag.Get("mapstructure")
if tag != "" && tag != ",squash" {
validKeys[tag] = field
} else if field.Anonymous && strings.Contains(tag, "squash") {
embeddedType := field.Type
if embeddedType.Kind() == reflect.Ptr {
embeddedType = embeddedType.Elem()
}
if embeddedType.Kind() == reflect.Struct {
for j := 0; j < embeddedType.NumField(); j++ {
embeddedField := embeddedType.Field(j)
embeddedTag := embeddedField.Tag.Get("mapstructure")
if embeddedTag != "" {
validKeys[embeddedTag] = embeddedField
}
}
}
}
}
findValidKeys(typ, validKeys)

// Check each key in the map to see if it's in the valid keys set
for key, value := range data {
Expand Down

0 comments on commit d22cc1c

Please sign in to comment.