Add common.JSONNumber type
parent
180b5655d5
commit
c3d58f0649
|
@ -0,0 +1,58 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
)
|
||||||
|
|
||||||
|
// JSONNumber is used instead of json.Number after upgrade to go 1.14
|
||||||
|
// to handle data which can be numbers in double quotes or possibly not numbers at all
|
||||||
|
// see https://github.com/golang/go/issues/37308
|
||||||
|
type JSONNumber string
|
||||||
|
|
||||||
|
// Float64 returns JSONNumber as float64
|
||||||
|
func (c JSONNumber) Float64() (float64, error) {
|
||||||
|
f, err := strconv.ParseFloat(string(c), 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64 returns JSONNumber as int64
|
||||||
|
func (c JSONNumber) Int64() (int64, error) {
|
||||||
|
i, err := strconv.ParseInt(string(c), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return i, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c JSONNumber) String() string {
|
||||||
|
return string(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON marsalls JSONNumber to []byte
|
||||||
|
// if possible, return a number without quotes, otherwise string value in quotes
|
||||||
|
func (c JSONNumber) MarshalJSON() ([]byte, error) {
|
||||||
|
if f, err := c.Float64(); err == nil {
|
||||||
|
return json.Marshal(f)
|
||||||
|
}
|
||||||
|
return json.Marshal(string(c))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshalls JSONNumber from []byte
|
||||||
|
// if the value is in quotes, remove them
|
||||||
|
func (c *JSONNumber) UnmarshalJSON(d []byte) error {
|
||||||
|
s := string(d)
|
||||||
|
l := len(s)
|
||||||
|
if l > 1 && s[0] == '"' && s[l-1] == '"' {
|
||||||
|
*c = JSONNumber(s[1 : l-1])
|
||||||
|
} else {
|
||||||
|
*c = JSONNumber(s)
|
||||||
|
}
|
||||||
|
glog.Info("JSONNumber ", s, ", ", *c)
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestJSONNumber_MarshalJSON(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
c JSONNumber
|
||||||
|
want []byte
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"0", JSONNumber("0"), []byte("0"), false},
|
||||||
|
{"1", JSONNumber("1"), []byte("1"), false},
|
||||||
|
{"2", JSONNumber("12341234.43214123"), []byte("12341234.43214123"), false},
|
||||||
|
{"3", JSONNumber("123E55"), []byte("1.23e+57"), false},
|
||||||
|
{"NaN", JSONNumber("dsfafdasf"), []byte("\"dsfafdasf\""), false},
|
||||||
|
{"empty", JSONNumber(""), []byte("\"\""), false},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := tt.c.MarshalJSON()
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("JSONNumber.MarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("JSONNumber.MarshalJSON() = %v, want %v", string(got), string(tt.want))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONNumber_UnmarshalJSON(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
c *JSONNumber
|
||||||
|
d []byte
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if err := tt.c.UnmarshalJSON(tt.d); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("JSONNumber.UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue