@@ -3235,6 +3235,231 @@ func TestDecoder_IgnoreUntaggedFieldsWithStruct(t *testing.T) {
32353235 }
32363236}
32373237
3238+ func TestDecoder_MultiTagInline (t * testing.T ) {
3239+ type Inner struct {
3240+ A int `yaml:"a"`
3241+ }
3242+
3243+ type Wrap struct {
3244+ Inner `yaml:",inline"`
3245+ }
3246+
3247+ input := map [string ]any {"a" : 1 }
3248+ var result Wrap
3249+
3250+ dec , err := NewDecoder (& DecoderConfig {
3251+ TagName : "config,yaml" ,
3252+ SquashTagOption : "inline" ,
3253+ WeaklyTypedInput : true ,
3254+ Result : & result ,
3255+ })
3256+ if err != nil {
3257+ t .Fatalf ("NewDecoder error: %v" , err )
3258+ }
3259+
3260+ if err := dec .Decode (input ); err != nil {
3261+ t .Fatalf ("Decode error: %v" , err )
3262+ }
3263+
3264+ if result .Inner .A != 1 {
3265+ t .Fatalf ("expected inline field A=1, got %d" , result .Inner .A )
3266+ }
3267+ }
3268+
3269+ func TestDecoder_MultiTagRemain (t * testing.T ) {
3270+ type Wrap struct {
3271+ Known string `yaml:"known"`
3272+ Extra map [string ]any `yaml:",remain"`
3273+ }
3274+
3275+ input := map [string ]any {
3276+ "known" : "ok" ,
3277+ "extra1" : "v1" ,
3278+ "extra2" : 2 ,
3279+ }
3280+ var result Wrap
3281+
3282+ dec , err := NewDecoder (& DecoderConfig {
3283+ TagName : "config,yaml" ,
3284+ WeaklyTypedInput : true ,
3285+ Result : & result ,
3286+ })
3287+ if err != nil {
3288+ t .Fatalf ("NewDecoder error: %v" , err )
3289+ }
3290+
3291+ if err := dec .Decode (input ); err != nil {
3292+ t .Fatalf ("Decode error: %v" , err )
3293+ }
3294+
3295+ if result .Known != "ok" {
3296+ t .Fatalf ("expected Known=ok, got %q" , result .Known )
3297+ }
3298+ if result .Extra == nil || len (result .Extra ) != 2 {
3299+ t .Fatalf ("expected Extra to contain 2 items, got %v" , result .Extra )
3300+ }
3301+ if result .Extra ["extra1" ] != "v1" {
3302+ t .Fatalf ("expected extra1=v1, got %v" , result .Extra ["extra1" ])
3303+ }
3304+ }
3305+
3306+ func TestDecoder_MultiTagBasic (t * testing.T ) {
3307+ type Person struct {
3308+ Name string `yaml:"name"`
3309+ Age int `json:"age"`
3310+ Email string `config:"email_address"`
3311+ }
3312+
3313+ input := map [string ]any {
3314+ "name" : "Alice" ,
3315+ "age" : 30 ,
3316+ "email_address" : "alice@example.com" ,
3317+ }
3318+ var result Person
3319+
3320+ dec , err := NewDecoder (& DecoderConfig {
3321+ TagName : "yaml,json,config" ,
3322+ Result : & result ,
3323+ })
3324+ if err != nil {
3325+ t .Fatalf ("NewDecoder error: %v" , err )
3326+ }
3327+
3328+ if err := dec .Decode (input ); err != nil {
3329+ t .Fatalf ("Decode error: %v" , err )
3330+ }
3331+
3332+ if result .Name != "Alice" {
3333+ t .Fatalf ("expected Name=Alice, got %q" , result .Name )
3334+ }
3335+ if result .Age != 30 {
3336+ t .Fatalf ("expected Age=30, got %d" , result .Age )
3337+ }
3338+ if result .Email != "alice@example.com" {
3339+ t .Fatalf ("expected Email=alice@example.com, got %q" , result .Email )
3340+ }
3341+ }
3342+
3343+ func TestDecoder_MultiTagPriority (t * testing.T ) {
3344+ // When both tags exist, the first tag name in the list takes precedence
3345+ type Item struct {
3346+ Value string `yaml:"yaml_value" json:"json_value"`
3347+ }
3348+
3349+ input := map [string ]any {
3350+ "yaml_value" : "from_yaml" ,
3351+ "json_value" : "from_json" ,
3352+ }
3353+
3354+ // Test yaml,json order - should use yaml tag
3355+ var result1 Item
3356+ dec1 , err := NewDecoder (& DecoderConfig {
3357+ TagName : "yaml,json" ,
3358+ Result : & result1 ,
3359+ })
3360+ if err != nil {
3361+ t .Fatalf ("NewDecoder error: %v" , err )
3362+ }
3363+ if err := dec1 .Decode (input ); err != nil {
3364+ t .Fatalf ("Decode error: %v" , err )
3365+ }
3366+ if result1 .Value != "from_yaml" {
3367+ t .Fatalf ("with yaml,json expected Value=from_yaml, got %q" , result1 .Value )
3368+ }
3369+
3370+ // Test json,yaml order - should use json tag
3371+ var result2 Item
3372+ dec2 , err := NewDecoder (& DecoderConfig {
3373+ TagName : "json,yaml" ,
3374+ Result : & result2 ,
3375+ })
3376+ if err != nil {
3377+ t .Fatalf ("NewDecoder error: %v" , err )
3378+ }
3379+ if err := dec2 .Decode (input ); err != nil {
3380+ t .Fatalf ("Decode error: %v" , err )
3381+ }
3382+ if result2 .Value != "from_json" {
3383+ t .Fatalf ("with json,yaml expected Value=from_json, got %q" , result2 .Value )
3384+ }
3385+ }
3386+
3387+ func TestDecoder_MultiTagWhitespace (t * testing.T ) {
3388+ type Person struct {
3389+ Name string `yaml:"name"`
3390+ Age int `json:"age"`
3391+ }
3392+
3393+ input := map [string ]any {
3394+ "name" : "Bob" ,
3395+ "age" : 25 ,
3396+ }
3397+ var result Person
3398+
3399+ // Test with whitespace around tag names
3400+ dec , err := NewDecoder (& DecoderConfig {
3401+ TagName : " yaml , json " ,
3402+ Result : & result ,
3403+ })
3404+ if err != nil {
3405+ t .Fatalf ("NewDecoder error: %v" , err )
3406+ }
3407+
3408+ if err := dec .Decode (input ); err != nil {
3409+ t .Fatalf ("Decode error: %v" , err )
3410+ }
3411+
3412+ if result .Name != "Bob" {
3413+ t .Fatalf ("expected Name=Bob, got %q" , result .Name )
3414+ }
3415+ if result .Age != 25 {
3416+ t .Fatalf ("expected Age=25, got %d" , result .Age )
3417+ }
3418+ }
3419+
3420+ func TestDecoder_MultiTagEmptyNames (t * testing.T ) {
3421+ type Person struct {
3422+ Name string `mapstructure:"name"`
3423+ }
3424+
3425+ input := map [string ]any {
3426+ "name" : "Charlie" ,
3427+ }
3428+
3429+ tests := []struct {
3430+ name string
3431+ tagName string
3432+ }{
3433+ {"leading comma" , ",yaml" },
3434+ {"trailing comma" , "yaml," },
3435+ {"multiple commas" , ",,yaml,," },
3436+ {"only commas" , ",,," },
3437+ {"empty with spaces" , " , , " },
3438+ }
3439+
3440+ for _ , tc := range tests {
3441+ t .Run (tc .name , func (t * testing.T ) {
3442+ var result Person
3443+ dec , err := NewDecoder (& DecoderConfig {
3444+ TagName : tc .tagName ,
3445+ Result : & result ,
3446+ })
3447+ if err != nil {
3448+ t .Fatalf ("NewDecoder error: %v" , err )
3449+ }
3450+
3451+ if err := dec .Decode (input ); err != nil {
3452+ t .Fatalf ("Decode error: %v" , err )
3453+ }
3454+
3455+ // With invalid/empty tag names, should fall back to mapstructure
3456+ if result .Name != "Charlie" {
3457+ t .Fatalf ("expected Name=Charlie (fallback to mapstructure), got %q" , result .Name )
3458+ }
3459+ })
3460+ }
3461+ }
3462+
32383463func TestDecoder_DecodeNilOption (t * testing.T ) {
32393464 t .Parallel ()
32403465
0 commit comments