fixedn: always correctly unmarshal Fixed8 values

Quoted or not, they should be unmarshalled without going through float64.
This commit is contained in:
Roman Khimov 2021-01-22 18:48:24 +03:00
parent 120ae4841f
commit ca258d6fbd
2 changed files with 29 additions and 21 deletions

View file

@ -1,7 +1,6 @@
package fixedn package fixedn
import ( import (
"encoding/json"
"errors" "errors"
"strconv" "strconv"
"strings" "strings"
@ -80,34 +79,30 @@ func Fixed8FromString(s string) (Fixed8, error) {
// UnmarshalJSON implements the json unmarshaller interface. // UnmarshalJSON implements the json unmarshaller interface.
func (f *Fixed8) UnmarshalJSON(data []byte) error { func (f *Fixed8) UnmarshalJSON(data []byte) error {
return f.unmarshalHelper(func(v interface{}) error { if len(data) > 2 {
return json.Unmarshal(data, v) if data[0] == '"' && data[len(data)-1] == '"' {
}) data = data[1 : len(data)-1]
}
}
return f.setFromString(string(data))
} }
// UnmarshalYAML implements the yaml unmarshaler interface. // UnmarshalYAML implements the yaml unmarshaler interface.
func (f *Fixed8) UnmarshalYAML(unmarshal func(interface{}) error) error { func (f *Fixed8) UnmarshalYAML(unmarshal func(interface{}) error) error {
return f.unmarshalHelper(unmarshal)
}
// unmarshalHelper is an underlying unmarshaller func for JSON and YAML.
func (f *Fixed8) unmarshalHelper(unmarshal func(interface{}) error) error {
var s string var s string
if err := unmarshal(&s); err == nil { err := unmarshal(&s)
p, err := Fixed8FromString(s) if err != nil {
if err != nil {
return err
}
*f = p
return nil
}
var fl float64
if err := unmarshal(&fl); err != nil {
return err return err
} }
return f.setFromString(s)
}
*f = Fixed8(decimals * fl) func (f *Fixed8) setFromString(s string) error {
p, err := Fixed8FromString(s)
if err != nil {
return err
}
*f = p
return nil return nil
} }

View file

@ -123,6 +123,19 @@ func TestFixed8UnmarshalJSON(t *testing.T) {
} }
} }
func TestFixed8_Unmarshal(t *testing.T) {
var expected = Fixed8(223719420)
var cases = []string{"2.2371942", `"2.2371942"`} // this easily gives 223719419 if interpreted as float
for _, c := range cases {
var u1, u2 Fixed8
assert.Nil(t, json.Unmarshal([]byte(c), &u1))
assert.Equal(t, expected, u1)
assert.Nil(t, yaml.Unmarshal([]byte(c), &u2))
assert.Equal(t, expected, u2)
}
}
func TestFixed8_MarshalJSON(t *testing.T) { func TestFixed8_MarshalJSON(t *testing.T) {
u, err := Fixed8FromString("123.4") u, err := Fixed8FromString("123.4")
assert.NoError(t, err) assert.NoError(t, err)