diff --git a/decode.go b/decode.go index b6e22a5e..e851feb4 100644 --- a/decode.go +++ b/decode.go @@ -488,6 +488,21 @@ func (d *Decoder) fileToNode(f *ast.File) ast.Node { func (d *Decoder) convertValue(v reflect.Value, typ reflect.Type, src ast.Node) (reflect.Value, error) { if typ.Kind() != reflect.String { if !v.Type().ConvertibleTo(typ) { + + // Special case for "strings -> floats" aka scientific notation + // If the destination type is a float and the source type is a string, check if we can + // use strconv.ParseFloat to convert the string to a float. + if (typ.Kind() == reflect.Float32 || typ.Kind() == reflect.Float64) && + v.Type().Kind() == reflect.String { + if f, err := strconv.ParseFloat(v.String(), 64); err == nil { + if typ.Kind() == reflect.Float32 { + return reflect.ValueOf(float32(f)), nil + } else if typ.Kind() == reflect.Float64 { + return reflect.ValueOf(f), nil + } + // else, fall through to the error below + } + } return reflect.Zero(typ), errTypeMismatch(typ, v.Type(), src.GetToken()) } return v.Convert(typ), nil diff --git a/decode_test.go b/decode_test.go index 7e9b6635..bf532b63 100644 --- a/decode_test.go +++ b/decode_test.go @@ -289,6 +289,10 @@ func TestDecoder(t *testing.T) { "v: 18446744073709551616", map[string]float32{"v": float32(math.MaxUint64 + 1)}, }, + { + "v: 1e-06", + map[string]float32{"v": 1e-6}, + }, // float64 { @@ -307,6 +311,10 @@ func TestDecoder(t *testing.T) { "v: 18446744073709551616", map[string]float64{"v": float64(math.MaxUint64 + 1)}, }, + { + "v: 1e-06", + map[string]float64{"v": 1e-06}, + }, // Timestamps { @@ -2932,4 +2940,4 @@ func TestMapKeyCustomUnmarshaler(t *testing.T) { if val != "value" { t.Fatalf("expected to have value \"value\", but got %q", val) } -} \ No newline at end of file +} diff --git a/encode_test.go b/encode_test.go index 3ff6f1c1..9ca44040 100644 --- a/encode_test.go +++ b/encode_test.go @@ -80,6 +80,16 @@ func TestEncoder(t *testing.T) { map[string]float32{"v": 0.99}, nil, }, + { + "v: 1e-06\n", + map[string]float32{"v": 1e-06}, + nil, + }, + { + "v: 1e-06\n", + map[string]float64{"v": 0.000001}, + nil, + }, { "v: 0.123456789\n", map[string]float64{"v": 0.123456789}, @@ -100,6 +110,16 @@ func TestEncoder(t *testing.T) { map[string]float64{"v": 1000000}, nil, }, + { + "v: 1e-06\n", + map[string]float64{"v": 0.000001}, + nil, + }, + { + "v: 1e-06\n", + map[string]float64{"v": 1e-06}, + nil, + }, { "v: .inf\n", map[string]interface{}{"v": math.Inf(0)},