From ba768f25089191df7a445de7183c860c3d49c02d Mon Sep 17 00:00:00 2001 From: anthony-tsang Date: Mon, 20 Aug 2018 14:14:32 -0700 Subject: [PATCH 1/2] dashboards Add Yaxis.AutoMin, YAxis.AutoMax, and custom Unmarshal * Add in the AutoMin and AutoMax fields for the Yaxis struct so we can work around the times when datadog's API returns a string when we expect a float64. * Add a custom UnmarshalJSON for Yaxis to utilize the new AutoMin and AutoMax fields. related error: "json: cannot unmarshal string into Go struct field Yaxis.min of type float64" --- dashboards.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/dashboards.go b/dashboards.go index 552b85d..fcd4c84 100644 --- a/dashboards.go +++ b/dashboards.go @@ -11,6 +11,7 @@ package datadog import ( "encoding/json" "fmt" + "strconv" ) // GraphDefinitionRequestStyle represents the graph style attributes @@ -53,10 +54,52 @@ type GraphEvent struct { type Yaxis struct { Min *float64 `json:"min,omitempty"` + AutoMin *bool Max *float64 `json:"max,omitempty"` + AutoMax * bool Scale *string `json:"scale,omitempty"` } +// UnmarshalJSON for Yaxis.Min/Yaxis.Max float64 to string. +func (y *Yaxis) UnmarshalJSON(data []byte) error { + type Alias Yaxis + wrapper := &struct { + Min *string `json:"min,omitempty"` + Max *string `json:"max,omitempty"` + *Alias + }{ + Alias: (*Alias)(y), + } + if err := json.Unmarshal(data, wrapper); err != nil { + return err + } + + if *wrapper.Min == "auto" { + *y.AutoMin = true + y.Min = nil + } else { + *wrapper.AutoMin = false + f, err := strconv.ParseFloat(*wrapper.Min, 64) + if err != nil { + return err + } + y.Min = &f + } + + if *wrapper.Max == "auto" { + *y.AutoMax = true + y.Max = nil + } else { + *wrapper.AutoMax = false + f, err := strconv.ParseFloat(*wrapper.Max, 64) + if err != nil { + return err + } + y.Max = &f + } + return nil +} + type Style struct { Palette *string `json:"palette,omitempty"` PaletteFlip *bool `json:"paletteFlip,omitempty"` From 305de43c61649ffd0cb602f888e94d82d84152b0 Mon Sep 17 00:00:00 2001 From: anthony-tsang Date: Wed, 22 Aug 2018 14:38:20 -0700 Subject: [PATCH 2/2] dashboards: Update custom Yaxis UnmarshalJSON and add unittests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Convert Yaxis.AutoMin and Yaxis.AutoMax to `bool` rather than `*bool` since they are local fields * Add json:"-" to `AutoMin` and `AutoMax` fields so the do not get marshalled * Change the wrapper Min/Max fields to be type *json.Number so that Min/Max can take a string (“auto”) if necessary. * I was running into an issue when {“min”: “auto”}, son.Unmarshal would complain `json: cannot unmarshal number into Go value of type string` * Add Unit Tests for marshaling and unmarshalling Yaxis <-> JSON --- dashboards.go | 36 +++++++++++----------- dashboards_test.go | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 18 deletions(-) create mode 100644 dashboards_test.go diff --git a/dashboards.go b/dashboards.go index fcd4c84..c09508e 100644 --- a/dashboards.go +++ b/dashboards.go @@ -11,7 +11,6 @@ package datadog import ( "encoding/json" "fmt" - "strconv" ) // GraphDefinitionRequestStyle represents the graph style attributes @@ -53,45 +52,46 @@ type GraphEvent struct { } type Yaxis struct { - Min *float64 `json:"min,omitempty"` - AutoMin *bool - Max *float64 `json:"max,omitempty"` - AutoMax * bool - Scale *string `json:"scale,omitempty"` + Min *float64 `json:"min,omitempty"` + AutoMin bool `json:"-"` + Max *float64 `json:"max,omitempty"` + AutoMax bool `json:"-"` + Scale *string `json:"scale,omitempty"` } -// UnmarshalJSON for Yaxis.Min/Yaxis.Max float64 to string. +// UnmarshalJSON is a Custom Unmarshal for Yaxis.Min/Yaxis.Max. If the datadog API +// returns "auto" for min or max, then we should set Yaxis.min or Yaxis.max to nil, +// respectively. func (y *Yaxis) UnmarshalJSON(data []byte) error { type Alias Yaxis wrapper := &struct { - Min *string `json:"min,omitempty"` - Max *string `json:"max,omitempty"` + Min *json.Number `json:"min,omitempty"` + Max *json.Number `json:"max,omitempty"` *Alias }{ Alias: (*Alias)(y), } - if err := json.Unmarshal(data, wrapper); err != nil { + + if err := json.Unmarshal(data, &wrapper); err != nil { return err } - if *wrapper.Min == "auto" { - *y.AutoMin = true + if wrapper.Min != nil && *wrapper.Min == "auto" { + y.AutoMin = true y.Min = nil } else { - *wrapper.AutoMin = false - f, err := strconv.ParseFloat(*wrapper.Min, 64) + f, err := wrapper.Min.Float64() if err != nil { return err } y.Min = &f } - if *wrapper.Max == "auto" { - *y.AutoMax = true + if wrapper.Max != nil && *wrapper.Max == "auto" { + y.AutoMax = true y.Max = nil } else { - *wrapper.AutoMax = false - f, err := strconv.ParseFloat(*wrapper.Max, 64) + f, err := wrapper.Max.Float64() if err != nil { return err } diff --git a/dashboards_test.go b/dashboards_test.go new file mode 100644 index 0000000..8ad9414 --- /dev/null +++ b/dashboards_test.go @@ -0,0 +1,77 @@ +package datadog + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" +) + +type Alias Yaxis + +type YAxisTestSuite struct { + suite.Suite + yJSON []byte + yMarshalledJSON []byte + y Yaxis + yAutoMinMaxJSON []byte + yAutoMinMaxMarshalledJSON []byte + yAutoMinMax Yaxis +} + +func (suite *YAxisTestSuite) SetupTest() { + // Custom Y.Min, Y.Max + suite.yJSON = []byte(`{"min":0,"max":1,"scale":"linear"}`) + suite.yMarshalledJSON = suite.yJSON + yMinFloat := float64(0) + yMaxFloat := float64(1) + yScale := "linear" + suite.y = Yaxis{ + Min: &yMinFloat, + AutoMin: false, + Max: &yMaxFloat, + AutoMax: false, + Scale: &yScale, + } + // Auto Y.Min, Y.Max + suite.yAutoMinMaxJSON = []byte(`{"min":"auto","max":"auto","scale":"linear"}`) + suite.yAutoMinMaxMarshalledJSON = []byte(`{"scale":"linear"}`) + suite.yAutoMinMax = Yaxis{ + Min: nil, + AutoMin: true, + Max: nil, + AutoMax: true, + Scale: &yScale, + } +} + +func (suite *YAxisTestSuite) TestYAxisJSONMarshalCustomMinMax() { + jsonData, err := json.Marshal(suite.y) + assert.Nil(suite.T(), err) + assert.Equal(suite.T(), suite.yMarshalledJSON, jsonData) +} + +func (suite *YAxisTestSuite) TestYAxisJSONUnmarshalCustomMinMax() { + var res Yaxis + err := json.Unmarshal(suite.yJSON, &res) + assert.Nil(suite.T(), err) + assert.Equal(suite.T(), suite.y, res) +} + +func (suite *YAxisTestSuite) TestYAxisJSONMarshalAutoMinMax() { + jsonData, err := json.Marshal(suite.yAutoMinMax) + assert.Nil(suite.T(), err) + assert.Equal(suite.T(), suite.yAutoMinMaxMarshalledJSON, jsonData) +} + +func (suite *YAxisTestSuite) TestYAxisJSONUnmarshalAutoMinMax() { + var res Yaxis + err := json.Unmarshal(suite.yAutoMinMaxJSON, &res) + assert.Nil(suite.T(), err) + assert.Equal(suite.T(), suite.yAutoMinMax, res) +} + +func TestYAxisTestSuite(t *testing.T) { + suite.Run(t, new(YAxisTestSuite)) +}