Skip to content

Commit 32ddeaf

Browse files
jmacdsagikazarmark
andauthored
Print qualified type name when ErrorUnused=true causes errors for unused keys in embedded fields (#113)
* Print qualified type name when ErrorUnused=true causes errors for unused keys in embedded fields * fmt * fix: lint violation Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com> --------- Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com> Co-authored-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
1 parent b9794a5 commit 32ddeaf

2 files changed

Lines changed: 62 additions & 1 deletion

File tree

mapstructure.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1605,8 +1605,14 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
16051605
}
16061606
sort.Strings(keys)
16071607

1608+
// Improve error message when name is empty by showing the target struct type
1609+
// in the case where it is empty for embedded structs.
1610+
errorName := name
1611+
if errorName == "" {
1612+
errorName = val.Type().String()
1613+
}
16081614
errs = append(errs, newDecodeError(
1609-
name,
1615+
errorName,
16101616
fmt.Errorf("has invalid keys: %s", strings.Join(keys, ", ")),
16111617
))
16121618
}

mapstructure_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3560,3 +3560,58 @@ func uintPtr(v uint) *uint { return &v }
35603560
func boolPtr(v bool) *bool { return &v }
35613561
func floatPtr(v float64) *float64 { return &v }
35623562
func interfacePtr(v any) *any { return &v }
3563+
3564+
// Test struct for embedded error message testing
3565+
type TestDatabaseConfig struct {
3566+
Host string `mapstructure:"host"`
3567+
Port int `mapstructure:"port"`
3568+
Username string `mapstructure:"username"`
3569+
}
3570+
3571+
type TestServerConfig struct {
3572+
TestDatabaseConfig `mapstructure:",squash"`
3573+
AppName string `mapstructure:"app_name"`
3574+
Debug bool `mapstructure:"debug"`
3575+
}
3576+
3577+
func TestDecoder_ErrorUnused_EmbeddedStruct_QualifiedTypeName(t *testing.T) {
3578+
t.Parallel()
3579+
3580+
// Input with an invalid key that should cause an error
3581+
input := map[string]any{
3582+
"host": "localhost",
3583+
"port": 5432,
3584+
"username": "admin",
3585+
"app_name": "myapp",
3586+
"debug": true,
3587+
"invalid_key": "this should cause an error", // This key doesn't exist in the struct
3588+
}
3589+
3590+
var config TestServerConfig
3591+
3592+
decoder, err := NewDecoder(&DecoderConfig{
3593+
ErrorUnused: true, // Enable error on unused keys
3594+
Result: &config,
3595+
})
3596+
if err != nil {
3597+
t.Fatalf("err: %s", err)
3598+
}
3599+
3600+
err = decoder.Decode(input)
3601+
if err == nil {
3602+
t.Fatal("expected error due to unused keys")
3603+
}
3604+
3605+
errorMessage := err.Error()
3606+
t.Logf("Error message: %s", errorMessage)
3607+
3608+
// Check that the error message contains the qualified struct type name
3609+
if !strings.Contains(errorMessage, "'mapstructure.TestServerConfig'") {
3610+
t.Errorf("Expected error message to contain qualified struct type 'mapstructure.TestServerConfig', got: %s", errorMessage)
3611+
}
3612+
3613+
// Check that unused keys are mentioned
3614+
if !strings.Contains(errorMessage, "invalid_key") {
3615+
t.Errorf("Expected error message to contain 'invalid_key', got: %s", errorMessage)
3616+
}
3617+
}

0 commit comments

Comments
 (0)