From 3c27c7335d980bbd155687202705e6d448a68545 Mon Sep 17 00:00:00 2001 From: Slavek Kabrda Date: Wed, 11 Mar 2020 17:45:18 +0100 Subject: [PATCH] Fix go regression in json.Number unmarshalling (#312) --- dashboards.go | 37 +++++++++++++------------------------ helper_test.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ helpers.go | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 24 deletions(-) diff --git a/dashboards.go b/dashboards.go index dc21460..2d9c2ed 100644 --- a/dashboards.go +++ b/dashboards.go @@ -114,8 +114,8 @@ type Yaxis struct { func (y *Yaxis) UnmarshalJSON(data []byte) error { type Alias Yaxis wrapper := &struct { - Min *json.Number `json:"min,omitempty"` - Max *json.Number `json:"max,omitempty"` + Min *interface{} `json:"min,omitempty"` + Max *interface{} `json:"max,omitempty"` *Alias }{ Alias: (*Alias)(y), @@ -125,31 +125,20 @@ func (y *Yaxis) UnmarshalJSON(data []byte) error { return err } - if wrapper.Min != nil { - if *wrapper.Min == "auto" { - y.AutoMin = true - y.Min = nil - } else { - f, err := wrapper.Min.Float64() - if err != nil { - return err - } - y.Min = &f - } + val, auto, err := GetFloatFromInterface(wrapper.Min) + if err != nil { + return fmt.Errorf(`faild parsing value for Yaxis.min: %s`, err.Error()) } + y.AutoMin = auto + y.Min = val - if wrapper.Max != nil { - if *wrapper.Max == "auto" { - y.AutoMax = true - y.Max = nil - } else { - f, err := wrapper.Max.Float64() - if err != nil { - return err - } - y.Max = &f - } + val, auto, err = GetFloatFromInterface(wrapper.Max) + if err != nil { + return fmt.Errorf(`faild parsing value for Yaxis.max: %s`, err.Error()) } + y.AutoMax = auto + y.Max = val + return nil } diff --git a/helper_test.go b/helper_test.go index f92bfc6..d4b36f5 100644 --- a/helper_test.go +++ b/helper_test.go @@ -128,3 +128,51 @@ func TestHelperGetStringId(t *testing.T) { assert.NotNil(t, err) assert.Contains(t, err.Error(), "unsupported id type") } + +func TestGetFloatFromInterface(t *testing.T) { + var input interface{} + + input = nil + val, auto, err := datadog.GetFloatFromInterface(nil) + assert.Nil(t, err) + assert.Equal(t, false, auto) + assert.Nil(t, val) + + input = 0.0 + val, auto, err = datadog.GetFloatFromInterface(&input) + assert.Nil(t, err) + assert.Equal(t, false, auto) + assert.Equal(t, 0.0, *val) + + input = 12.3 + val, auto, err = datadog.GetFloatFromInterface(&input) + assert.Nil(t, err) + assert.Equal(t, false, auto) + assert.Equal(t, 12.3, *val) + + input = 123 + val, auto, err = datadog.GetFloatFromInterface(&input) + assert.Nil(t, err) + assert.Equal(t, false, auto) + assert.Equal(t, 123.0, *val) + + input = int64(1234567890123456789.0) + val, auto, err = datadog.GetFloatFromInterface(&input) + assert.Nil(t, err) + assert.Equal(t, false, auto) + assert.Equal(t, 1234567890123456789.0, *val) + + input = "auto" + val, auto, err = datadog.GetFloatFromInterface(&input) + assert.Nil(t, err) + assert.Equal(t, true, auto) + assert.Nil(t, val) + + input = "wrong!" + val, auto, err = datadog.GetFloatFromInterface(&input) + assert.NotNil(t, err) + + input = false + val, auto, err = datadog.GetFloatFromInterface(&input) + assert.NotNil(t, err) +} diff --git a/helpers.go b/helpers.go index d8d14f7..553808d 100644 --- a/helpers.go +++ b/helpers.go @@ -11,6 +11,7 @@ package datadog import ( "encoding/json" "errors" + "fmt" "math" "strconv" ) @@ -122,3 +123,43 @@ func GetStringId(id interface{}) (string, error) { return "", errors.New("unsupported id type") } } + +func GetFloatFromInterface(intf *interface{}) (*float64, bool, error) { + var result *float64 + var auto bool + + if intf != nil { + val := *intf + switch tp := val.(type) { + case float32: + fv := float64(val.(float32)) + result = &fv + case float64: + fv := val.(float64) + result = &fv + case int: + fv := float64(val.(int)) + result = &fv + case int32: + fv := float64(val.(int32)) + result = &fv + case int64: + fv := float64(val.(int64)) + result = &fv + case string: + fv := val.(string) + if fv == "auto" { + auto = true + } else { + f, err := strconv.ParseFloat(fv, 64) + if err != nil { + return nil, false, err + } + result = &f + } + default: + return nil, false, fmt.Errorf(`bad type "%v" for Yaxis.min, expected "auto" or a number`, tp) + } + } + return result, auto, nil +}