Add JSON unmarshallers for numeric types from util (#83)

Uint160, Uint256, Fixed8 now have UnmarshalJSON method.
This commit is contained in:
Evgenii Stratonikov 2018-05-09 08:20:16 +03:00 committed by Anthony De Meulemeester
parent 35551282b0
commit 1d9045877c
8 changed files with 110 additions and 4 deletions

View file

@ -1 +1 @@
0.44.2 0.44.3

View file

@ -2,6 +2,7 @@ package util
import ( import (
"bytes" "bytes"
"encoding/json"
"errors" "errors"
"strconv" "strconv"
"strings" "strings"
@ -49,7 +50,8 @@ func NewFixed8(val int) Fixed8 {
return Fixed8(decimals * val) return Fixed8(decimals * val)
} }
// Fixed8DecodeString // Fixed8DecodeString parses s which must be a fixed point number
// with precision up to 10^-8
func Fixed8DecodeString(s string) (Fixed8, error) { func Fixed8DecodeString(s string) (Fixed8, error) {
parts := strings.SplitN(s, ".", 2) parts := strings.SplitN(s, ".", 2)
ip, err := strconv.Atoi(parts[0]) ip, err := strconv.Atoi(parts[0])
@ -68,3 +70,24 @@ func Fixed8DecodeString(s string) (Fixed8, error) {
} }
return Fixed8(ip*decimals + fp), nil return Fixed8(ip*decimals + fp), nil
} }
// UnmarshalJSON implements the json unmarshaller interface.
func (f *Fixed8) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err == nil {
p, err := Fixed8DecodeString(s)
if err != nil {
return err
}
*f = p
return nil
}
var fl float64
if err := json.Unmarshal(data, &fl); err != nil {
return err
}
*f = Fixed8(decimals * fl)
return nil
}

View file

@ -1,6 +1,7 @@
package util package util
import ( import (
"encoding/json"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -18,7 +19,7 @@ func TestNewFixed8(t *testing.T) {
func TestFixed8DecodeString(t *testing.T) { func TestFixed8DecodeString(t *testing.T) {
// Fixed8DecodeString works correctly with integers // Fixed8DecodeString works correctly with integers
ivalues := []string{"9000", "100000000", "5", "10945"} ivalues := []string{"9000", "100000000", "5", "10945"}
for _, val:= range ivalues { for _, val := range ivalues {
n, err := Fixed8DecodeString(val) n, err := Fixed8DecodeString(val)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, val, n.String()) assert.Equal(t, val, n.String())
@ -36,3 +37,21 @@ func TestFixed8DecodeString(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, Fixed8(90123410000), n) assert.Equal(t, Fixed8(90123410000), n)
} }
func TestFixed8UnmarshalJSON(t *testing.T) {
fl := float64(123.45)
str := "123.45"
expected, _ := Fixed8DecodeString(str)
// UnmarshalJSON should decode floats
var u1 Fixed8
s, _ := json.Marshal(fl)
assert.Nil(t, json.Unmarshal(s, &u1))
assert.Equal(t, expected, u1)
// UnmarshalJSON should decode strings
var u2 Fixed8
s, _ = json.Marshal(str)
assert.Nil(t, json.Unmarshal(s, &u2))
assert.Equal(t, expected, u2)
}

View file

@ -18,7 +18,7 @@ func RandomString(n int) string {
return string(b) return string(b)
} }
// RamdomInt returns a ramdom integer betweeen min and max. // RandomInt returns a ramdom integer betweeen min and max.
func RandomInt(min, max int) int { func RandomInt(min, max int) int {
return min + rand.Intn(max-min) return min + rand.Intn(max-min)
} }

View file

@ -5,6 +5,7 @@ import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings"
"golang.org/x/crypto/ripemd160" "golang.org/x/crypto/ripemd160"
) )
@ -77,6 +78,19 @@ func (u Uint160) Equals(other Uint160) bool {
return true return true
} }
// UnmarshalJSON implements the json unmarshaller interface.
func (u *Uint160) UnmarshalJSON(data []byte) (err error) {
var js string
if err = json.Unmarshal(data, &js); err != nil {
return err
}
if strings.HasPrefix(js, "0x") {
js = js[2:]
}
*u, err = Uint160DecodeString(js)
return err
}
// MarshalJSON implements the json marshaller interface. // MarshalJSON implements the json marshaller interface.
func (u Uint160) MarshalJSON() ([]byte, error) { func (u Uint160) MarshalJSON() ([]byte, error) {
return json.Marshal( return json.Marshal(

View file

@ -2,11 +2,29 @@ package util
import ( import (
"encoding/hex" "encoding/hex"
"encoding/json"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestUint160UnmarshalJSON(t *testing.T) {
str := "2d3b96ae1bcc5a585e075e3b81920210dec16302"
expected, _ := Uint160DecodeString(str)
// UnmarshalJSON should decode hex-strings
var u1 Uint160
s, _ := json.Marshal(str)
assert.Nil(t, json.Unmarshal(s, &u1))
assert.True(t, expected.Equals(u1))
// UnmarshalJSON should decode hex-strings prefixed by 0x
var u2 Uint160
s, _ = json.Marshal("0x" + str)
assert.Nil(t, json.Unmarshal(s, &u2))
assert.True(t, expected.Equals(u2))
}
func TestUInt160DecodeString(t *testing.T) { func TestUInt160DecodeString(t *testing.T) {
hexStr := "2d3b96ae1bcc5a585e075e3b81920210dec16302" hexStr := "2d3b96ae1bcc5a585e075e3b81920210dec16302"
val, err := Uint160DecodeString(hexStr) val, err := Uint160DecodeString(hexStr)

View file

@ -4,6 +4,7 @@ import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings"
) )
const uint256Size = 32 const uint256Size = 32
@ -59,6 +60,19 @@ func (u Uint256) String() string {
return hex.EncodeToString(ArrayReverse(u.Bytes())) return hex.EncodeToString(ArrayReverse(u.Bytes()))
} }
// UnmarshalJSON implements the json unmarshaller interface.
func (u *Uint256) UnmarshalJSON(data []byte) (err error) {
var js string
if err = json.Unmarshal(data, &js); err != nil {
return err
}
if strings.HasPrefix(js, "0x") {
js = js[2:]
}
*u, err = Uint256DecodeString(js)
return err
}
// MarshalJSON implements the json marshaller interface. // MarshalJSON implements the json marshaller interface.
func (u Uint256) MarshalJSON() ([]byte, error) { func (u Uint256) MarshalJSON() ([]byte, error) {
return json.Marshal(fmt.Sprintf("0x%s", u.String())) return json.Marshal(fmt.Sprintf("0x%s", u.String()))

View file

@ -2,11 +2,29 @@ package util
import ( import (
"encoding/hex" "encoding/hex"
"encoding/json"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestUint256UnmarshalJSON(t *testing.T) {
str := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
expected, _ := Uint256DecodeString(str)
// UnmarshalJSON should decode hex-strings
var u1 Uint256
s, _ := json.Marshal(str)
assert.Nil(t, json.Unmarshal(s, &u1))
assert.True(t, expected.Equals(u1))
// UnmarshalJSON should decode hex-strings prefixed by 0x
var u2 Uint256
s, _ = json.Marshal("0x" + str)
assert.Nil(t, json.Unmarshal(s, &u2))
assert.True(t, expected.Equals(u2))
}
func TestUint256DecodeString(t *testing.T) { func TestUint256DecodeString(t *testing.T) {
hexStr := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d" hexStr := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
val, err := Uint256DecodeString(hexStr) val, err := Uint256DecodeString(hexStr)