Skip to content

Commit

Permalink
Add methods to model.Duration for JSON marshalling and unmarshalling
Browse files Browse the repository at this point in the history
Add methods to model.Duration structs to allow them to be serialized
and unserialized to/from JSON. This helps downstream consumers of the
structs that attempt to use them in objects that are expected to be
able to be represented as JSON (such as Cortex).

Signed-off-by: Nick Pillitteri <nick.pillitteri@grafana.com>
  • Loading branch information
56quarters committed Mar 5, 2021
1 parent 47ee79a commit 2a23014
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
17 changes: 17 additions & 0 deletions model/time.go
Expand Up @@ -14,6 +14,7 @@
package model

import (
"encoding/json"
"fmt"
"math"
"regexp"
Expand Down Expand Up @@ -254,6 +255,22 @@ func (d Duration) String() string {
return r
}

// MarshalJSON implements the json.Marshaler interface.
func (d Duration) MarshalJSON() ([]byte, error) {
return json.Marshal(d.String())
}

// UnmarshalJSON implements the json.Unmarshaler interface.
func (d *Duration) UnmarshalJSON(bytes []byte) error {
var err error
var s string
if err := json.Unmarshal(bytes, &s); err != nil {
return err
}
*d, err = ParseDuration(s)
return err
}

// MarshalText implements the encoding.TextMarshaler interface.
func (d *Duration) MarshalText() ([]byte, error) {
return []byte(d.String()), nil
Expand Down
77 changes: 77 additions & 0 deletions model/time_test.go
Expand Up @@ -14,6 +14,7 @@
package model

import (
"encoding/json"
"strconv"
"testing"
"time"
Expand Down Expand Up @@ -230,6 +231,82 @@ func TestDuration_UnmarshalText(t *testing.T) {
}
}

func TestDuration_UnmarshalJSON(t *testing.T) {
var cases = []struct {
in string
out time.Duration

expectedString string
}{
{
in: `"0"`,
out: 0,
expectedString: `"0s"`,
}, {
in: `"0w"`,
out: 0,
expectedString: `"0s"`,
}, {
in: `"0s"`,
out: 0,
}, {
in: `"324ms"`,
out: 324 * time.Millisecond,
}, {
in: `"3s"`,
out: 3 * time.Second,
}, {
in: `"5m"`,
out: 5 * time.Minute,
}, {
in: `"1h"`,
out: time.Hour,
}, {
in: `"4d"`,
out: 4 * 24 * time.Hour,
}, {
in: `"4d1h"`,
out: 4*24*time.Hour + time.Hour,
}, {
in: `"14d"`,
out: 14 * 24 * time.Hour,
expectedString: `"2w"`,
}, {
in: `"3w"`,
out: 3 * 7 * 24 * time.Hour,
}, {
in: `"3w2d1h"`,
out: 3*7*24*time.Hour + 2*24*time.Hour + time.Hour,
expectedString: `"23d1h"`,
}, {
in: `"10y"`,
out: 10 * 365 * 24 * time.Hour,
},
}

for _, c := range cases {
var d Duration
err := json.Unmarshal([]byte(c.in), &d)
if err != nil {
t.Errorf("Unexpected error on input %q", c.in)
}
if time.Duration(d) != c.out {
t.Errorf("Expected %v but got %v", c.out, d)
}
expectedString := c.expectedString
if c.expectedString == "" {
expectedString = c.in
}
bytes, err := json.Marshal(d)
if err != nil {
t.Errorf("Unexpected error on marshal of %v: %s", d, err)
}
if string(bytes) != expectedString {
t.Errorf("Expected duration string %q but got %q", c.in, d.String())
}
}
}

func TestParseBadDuration(t *testing.T) {
var cases = []string{
"1",
Expand Down

0 comments on commit 2a23014

Please sign in to comment.