@@ -699,7 +699,7 @@ func (d *Decoder) decodeString(name string, data any, val reflect.Value) error {
699699 case reflect .Uint8 :
700700 var uints []uint8
701701 if dataKind == reflect .Array {
702- uints = make ([]uint8 , dataVal .Len (), dataVal . Len () )
702+ uints = make ([]uint8 , dataVal .Len ())
703703 for i := range uints {
704704 uints [i ] = dataVal .Index (i ).Interface ().(uint8 )
705705 }
@@ -1091,7 +1091,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
10911091 )
10921092 }
10931093
1094- tagValue := f . Tag . Get ( d .config .TagName )
1094+ tagValue , _ := getTagValue ( f , d .config .TagName )
10951095 keyName := d .config .MapFieldName (f .Name )
10961096
10971097 if tagValue == "" && d .config .IgnoreUntaggedFields {
@@ -1112,12 +1112,12 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
11121112 continue
11131113 }
11141114 // If "omitempty" is specified in the tag, it ignores empty values.
1115- if strings .Index (tagValue [index + 1 :], "omitempty" ) != - 1 && isEmptyValue (v ) {
1115+ if strings .Contains (tagValue [index + 1 :], "omitempty" ) && isEmptyValue (v ) {
11161116 continue
11171117 }
11181118
11191119 // If "omitzero" is specified in the tag, it ignores zero values.
1120- if strings .Index (tagValue [index + 1 :], "omitzero" ) != - 1 && v .IsZero () {
1120+ if strings .Contains (tagValue [index + 1 :], "omitzero" ) && v .IsZero () {
11211121 continue
11221122 }
11231123
@@ -1137,7 +1137,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
11371137 )
11381138 }
11391139 } else {
1140- if strings .Index (tagValue [index + 1 :], "remain" ) != - 1 {
1140+ if strings .Contains (tagValue [index + 1 :], "remain" ) {
11411141 if v .Kind () != reflect .Map {
11421142 return newDecodeError (
11431143 name + "." + f .Name ,
@@ -1153,7 +1153,7 @@ func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val re
11531153 }
11541154 }
11551155
1156- deep = deep || strings .Index (tagValue [index + 1 :], "deep" ) != - 1
1156+ deep = deep || strings .Contains (tagValue [index + 1 :], "deep" )
11571157
11581158 if keyNameTagValue := tagValue [:index ]; keyNameTagValue != "" {
11591159 keyName = keyNameTagValue
@@ -1543,7 +1543,10 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
15431543 remain := false
15441544
15451545 // We always parse the tags cause we're looking for other tags too
1546- tagParts := strings .Split (fieldType .Tag .Get (d .config .TagName ), "," )
1546+ tagParts := getTagParts (fieldType , d .config .TagName )
1547+ if len (tagParts ) == 0 {
1548+ tagParts = []string {"" }
1549+ }
15471550 for _ , tag := range tagParts [1 :] {
15481551 if tag == d .config .SquashTagOption {
15491552 squash = true
@@ -1600,7 +1603,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
16001603 field , fieldValue := f .field , f .val
16011604 fieldName := field .Name
16021605
1603- tagValue := field . Tag . Get ( d .config .TagName )
1606+ tagValue , _ := getTagValue ( field , d .config .TagName )
16041607 if tagValue == "" && d .config .IgnoreUntaggedFields {
16051608 continue
16061609 }
@@ -1784,7 +1787,7 @@ func isStructTypeConvertibleToMap(typ reflect.Type, checkMapstructureTags bool,
17841787 if f .PkgPath == "" && ! checkMapstructureTags { // check for unexported fields
17851788 return true
17861789 }
1787- if checkMapstructureTags && f . Tag . Get ( tagName ) != "" { // check for mapstructure tags inside
1790+ if checkMapstructureTags && hasAnyTag ( f , tagName ) { // check for mapstructure tags inside
17881791 return true
17891792 }
17901793 }
@@ -1812,3 +1815,36 @@ func dereferencePtrToStructIfNeeded(v reflect.Value, tagName string) reflect.Val
18121815 return v
18131816 }
18141817}
1818+
1819+ func hasAnyTag (field reflect.StructField , tagName string ) bool {
1820+ _ , ok := getTagValue (field , tagName )
1821+ return ok
1822+ }
1823+
1824+ func getTagParts (field reflect.StructField , tagName string ) []string {
1825+ tagValue , ok := getTagValue (field , tagName )
1826+ if ! ok {
1827+ return nil
1828+ }
1829+ return strings .Split (tagValue , "," )
1830+ }
1831+
1832+ func getTagValue (field reflect.StructField , tagName string ) (string , bool ) {
1833+ for _ , name := range splitTagNames (tagName ) {
1834+ if tag := field .Tag .Get (name ); tag != "" {
1835+ return tag , true
1836+ }
1837+ }
1838+ return "" , false
1839+ }
1840+
1841+ func splitTagNames (tagName string ) []string {
1842+ if tagName == "" {
1843+ return []string {"mapstructure" }
1844+ }
1845+ parts := strings .Split (tagName , "," )
1846+ for i , name := range parts {
1847+ parts [i ] = strings .TrimSpace (name )
1848+ }
1849+ return parts
1850+ }
0 commit comments