Skip to content

Commit

Permalink
types: Dec.MarshalJSON now marshals as a normal decimal string
Browse files Browse the repository at this point in the history
  • Loading branch information
ValarDragon committed Oct 16, 2018
1 parent 2803830 commit 20cc13e
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 4 deletions.
2 changes: 2 additions & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ BREAKING CHANGES
* [x/stake] \#2412 Added an unbonding validator queue to EndBlock to automatically update validator.Status when finished Unbonding
* [x/stake] \#2500 Block conflicting redelegations until we add an index
* [x/params] Global Paramstore refactored
* [types] \#2506 sdk.Dec MarshalJSON now marshals as a normal Decimal, with 10 digits of decimal precision


* Tendermint
* Update tendermint version from v0.23.0 to v0.25.0, notable changes
Expand Down
33 changes: 29 additions & 4 deletions types/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,17 +407,36 @@ func (d *Dec) UnmarshalAmino(text string) (err error) {
return nil
}

// MarshalJSON defines custom encoding scheme
// MarshalJSON marshals the decimal
func (d Dec) MarshalJSON() ([]byte, error) {
if d.Int == nil {
return nilJSON, nil
}

bz, err := d.Int.MarshalText()
if err != nil {
return nil, err
}
return json.Marshal(string(bz))
var bzWDec []byte
// TODO: Remove trailing zeros
// case 1, pure decimal
if len(bz) <= 10 {
bzWDec = make([]byte, 12)
// 0. prefix
bzWDec[0] = byte('0')
bzWDec[1] = byte('.')
// set relevant digits to 0
for i := 0; i < 10-len(bz); i++ {
bzWDec[i+2] = byte('0')
}
// set last few digits
copy(bzWDec[2+(10-len(bz)):], bz)
} else {
bzWDec = make([]byte, len(bz)+1)
copy(bzWDec, bz[:len(bz)-10])
bzWDec[len(bz)-10] = byte('.')
copy(bzWDec[len(bz)-9:], bz[len(bz)-10:])
}
return json.Marshal(string(bzWDec))
}

// UnmarshalJSON defines custom decoding scheme
Expand All @@ -431,7 +450,13 @@ func (d *Dec) UnmarshalJSON(bz []byte) error {
if err != nil {
return err
}
return d.Int.UnmarshalText([]byte(text))
// TODO: Reuse dec allocation
newDec, err := NewDecFromStr(text)
if err != nil {
return err
}
d.Int = newDec.Int
return nil
}

//___________________________________________________________________________________
Expand Down
40 changes: 40 additions & 0 deletions types/decimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"math/big"
"testing"

"github.com/stretchr/testify/assert"

"github.com/cosmos/cosmos-sdk/codec"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -248,6 +250,44 @@ func TestToLeftPadded(t *testing.T) {

var cdc = codec.New()

func TestDecMarshalJSON(t *testing.T) {
decimal := func(i int64) Dec {
d := NewDec(0)
d.Int = new(big.Int).SetInt64(i)
return d
}
tests := []struct {
name string
d Dec
want string
wantErr bool // if wantErr = false, will also attempt unmarshaling
}{
{"zero", decimal(0), "\"0.0000000000\"", false},
{"one", decimal(1), "\"0.0000000001\"", false},
{"ten", decimal(10), "\"0.0000000010\"", false},
{"12340", decimal(12340), "\"0.0000012340\"", false},
{"zeroInt", NewDec(0), "\"0.0000000000\"", false},
{"oneInt", NewDec(1), "\"1.0000000000\"", false},
{"tenInt", NewDec(10), "\"10.0000000000\"", false},
{"12340Int", NewDec(12340), "\"12340.0000000000\"", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tt.d.MarshalJSON()
if (err != nil) != tt.wantErr {
t.Errorf("Dec.MarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr {
assert.Equal(t, tt.want, string(got), "incorrect marshalled value")
unmarshalledDec := NewDec(0)
unmarshalledDec.UnmarshalJSON(got)
assert.Equal(t, tt.d, unmarshalledDec, "incorrect unmarshalled value")
}
})
}
}

func TestZeroDeserializationJSON(t *testing.T) {
d := Dec{new(big.Int)}
err := cdc.UnmarshalJSON([]byte(`"0"`), &d)
Expand Down

0 comments on commit 20cc13e

Please sign in to comment.