@@ -3688,6 +3688,8 @@ type TestMapFieldName struct {
36883688}
36893689
36903690func TestDecoder_MapFieldNameMapFromStruct (t * testing.T ) {
3691+ t .Parallel ()
3692+
36913693 var structKeys map [string ]any
36923694
36933695 decoder , err := NewDecoder (& DecoderConfig {
@@ -3723,6 +3725,8 @@ func TestDecoder_MapFieldNameMapFromStruct(t *testing.T) {
37233725}
37243726
37253727func TestDecoder_MapFieldNameStructFromMap (t * testing.T ) {
3728+ t .Parallel ()
3729+
37263730 foo := TestMapFieldName {}
37273731
37283732 decoder , err := NewDecoder (& DecoderConfig {
@@ -3759,3 +3763,96 @@ func TestDecoder_MapFieldNameStructFromMap(t *testing.T) {
37593763 t .Fatal ("expected Username to be bar" )
37603764 }
37613765}
3766+
3767+ func TestDecoder_MapFieldNameWithMatchName (t * testing.T ) {
3768+ t .Parallel ()
3769+
3770+ type Target struct {
3771+ HostName string
3772+ Username string
3773+ }
3774+
3775+ input := map [string ]any {
3776+ "HOST_NAME" : "server1" ,
3777+ "user_name" : "admin" ,
3778+ }
3779+
3780+ var result Target
3781+ decoder , err := NewDecoder (& DecoderConfig {
3782+ Result : & result ,
3783+ MapFieldName : func (s string ) string {
3784+ // Convert HostName -> host_name, Username -> user_name
3785+ if s == "HostName" {
3786+ return "host_name"
3787+ }
3788+ if s == "Username" {
3789+ return "user_name"
3790+ }
3791+ return s
3792+ },
3793+ MatchName : strings .EqualFold , // Case-insensitive fallback
3794+ })
3795+ if err != nil {
3796+ t .Fatalf ("err: %s" , err )
3797+ }
3798+
3799+ err = decoder .Decode (input )
3800+ if err != nil {
3801+ t .Fatalf ("err: %s" , err )
3802+ }
3803+
3804+ // HOST_NAME should match host_name via case-insensitive MatchName
3805+ if result .HostName != "server1" {
3806+ t .Fatalf ("expected HostName to be 'server1', got '%s'" , result .HostName )
3807+ }
3808+
3809+ // user_name matches exactly
3810+ if result .Username != "admin" {
3811+ t .Fatalf ("expected Username to be 'admin', got '%s'" , result .Username )
3812+ }
3813+ }
3814+
3815+ func TestDecoder_MapFieldNameWithIgnoreUntaggedFields (t * testing.T ) {
3816+ t .Parallel ()
3817+
3818+ type Target struct {
3819+ TaggedField string `mapstructure:"tagged_field"`
3820+ UntaggedField string
3821+ }
3822+
3823+ input := map [string ]any {
3824+ "tagged_field" : "tagged_value" ,
3825+ "untagged_field" : "untagged_value" ,
3826+ }
3827+
3828+ var result Target
3829+ decoder , err := NewDecoder (& DecoderConfig {
3830+ Result : & result ,
3831+ IgnoreUntaggedFields : true ,
3832+ MapFieldName : func (s string ) string {
3833+ // This would convert UntaggedField -> untagged_field,
3834+ // but IgnoreUntaggedFields takes precedence
3835+ if s == "UntaggedField" {
3836+ return "untagged_field"
3837+ }
3838+ return s
3839+ },
3840+ })
3841+ if err != nil {
3842+ t .Fatalf ("err: %s" , err )
3843+ }
3844+
3845+ err = decoder .Decode (input )
3846+ if err != nil {
3847+ t .Fatalf ("err: %s" , err )
3848+ }
3849+
3850+ if result .TaggedField != "tagged_value" {
3851+ t .Fatalf ("expected TaggedField to be 'tagged_value', got '%s'" , result .TaggedField )
3852+ }
3853+
3854+ // UntaggedField should remain empty because IgnoreUntaggedFields is true
3855+ if result .UntaggedField != "" {
3856+ t .Fatalf ("expected UntaggedField to be empty due to IgnoreUntaggedFields, got '%s'" , result .UntaggedField )
3857+ }
3858+ }
0 commit comments