diff --git a/mapstructure.go b/mapstructure.go index 3643901f..4bd8f97a 100644 --- a/mapstructure.go +++ b/mapstructure.go @@ -571,7 +571,11 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) } val.SetString(string(uints)) default: - converted = false + if dataVal.Len() == 1 { + return d.decodeString(name, dataVal.Index(0).Interface(), val) + } else { + converted = false + } } default: converted = false @@ -624,6 +628,15 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) er "error decoding json.Number into %s: %s", name, err) } val.SetInt(i) + case dataKind == reflect.Slice && d.config.WeaklyTypedInput, + dataKind == reflect.Array && d.config.WeaklyTypedInput: + if dataVal.Len() == 1 { + return d.decodeInt(name, dataVal.Index(0).Interface(), val) + } else { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } default: return fmt.Errorf( "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", @@ -685,6 +698,15 @@ func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) e name, i) } val.SetUint(uint64(i)) + case dataKind == reflect.Slice && d.config.WeaklyTypedInput, + dataKind == reflect.Array && d.config.WeaklyTypedInput: + if dataVal.Len() == 1 { + return d.decodeUint(name, dataVal.Index(0).Interface(), val) + } else { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } default: return fmt.Errorf( "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", @@ -716,6 +738,15 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) e } else { return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) } + case dataKind == reflect.Slice && d.config.WeaklyTypedInput, + dataKind == reflect.Array && d.config.WeaklyTypedInput: + if dataVal.Len() == 1 { + return d.decodeBool(name, dataVal.Index(0).Interface(), val) + } else { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } default: return fmt.Errorf( "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", @@ -763,6 +794,15 @@ func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) "error decoding json.Number into %s: %s", name, err) } val.SetFloat(i) + case dataKind == reflect.Slice && d.config.WeaklyTypedInput, + dataKind == reflect.Array && d.config.WeaklyTypedInput: + if dataVal.Len() == 1 { + return d.decodeFloat(name, dataVal.Index(0).Interface(), val) + } else { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s'", + name, val.Type(), dataVal.Type()) + } default: return fmt.Errorf( "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", diff --git a/mapstructure_test.go b/mapstructure_test.go index 53b2d0a4..3362c921 100644 --- a/mapstructure_test.go +++ b/mapstructure_test.go @@ -201,6 +201,10 @@ type TypeConversionResult struct { StringToIntSlice []int StringToStrArray [1]string StringToIntArray [1]int + SliceToString string + SliceToInt64 int64 + SliceToTrue bool + SliceToFalse bool SliceToMap map[string]interface{} MapToSlice []interface{} ArrayToMap map[string]interface{} @@ -1090,6 +1094,10 @@ func TestDecode_TypeConversion(t *testing.T) { "StringToIntSlice": "42", "StringToStrArray": "A", "StringToIntArray": "42", + "SliceToString": []string{"42"}, + "SliceToInt64": []string{"42"}, + "SliceToTrue": []string{"true"}, + "SliceToFalse": []string{""}, "SliceToMap": []interface{}{}, "MapToSlice": map[string]interface{}{}, "ArrayToMap": []interface{}{}, @@ -1136,6 +1144,10 @@ func TestDecode_TypeConversion(t *testing.T) { StringToIntSlice: []int{42}, StringToStrArray: [1]string{"A"}, StringToIntArray: [1]int{42}, + SliceToString: "42", + SliceToInt64: 42, + SliceToTrue: true, + SliceToFalse: false, SliceToMap: map[string]interface{}{}, MapToSlice: []interface{}{}, ArrayToMap: map[string]interface{}{},