common: using `ParseUint` instead of `ParseInt` (#30020)

Since Decimal is defined as unsiged `uint64`, we should use `strconv.ParseUint` instead of `strconv.ParseInt` during unmarshalling.

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
This commit is contained in:
Halimao 2024-06-19 17:06:52 +08:00 committed by GitHub
parent 0e3a0a693c
commit c11aac249d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 1 deletions

View File

@ -468,7 +468,7 @@ func (d *Decimal) UnmarshalJSON(input []byte) error {
if !isString(input) {
return &json.UnmarshalTypeError{Value: "non-string", Type: reflect.TypeOf(uint64(0))}
}
if i, err := strconv.ParseInt(string(input[1:len(input)-1]), 10, 64); err == nil {
if i, err := strconv.ParseUint(string(input[1:len(input)-1]), 10, 64); err == nil {
*d = Decimal(i)
return nil
} else {

View File

@ -21,6 +21,7 @@ import (
"database/sql/driver"
"encoding/json"
"fmt"
"math"
"math/big"
"reflect"
"strings"
@ -595,3 +596,29 @@ func BenchmarkPrettyDuration(b *testing.B) {
}
b.Logf("Post %s", a)
}
func TestDecimalUnmarshalJSON(t *testing.T) {
// These should error
for _, tc := range []string{``, `"`, `""`, `"-1"`} {
if err := new(Decimal).UnmarshalJSON([]byte(tc)); err == nil {
t.Errorf("input %s should cause error", tc)
}
}
// These should succeed
for _, tc := range []struct {
input string
want uint64
}{
{`"0"`, 0},
{`"9223372036854775807"`, math.MaxInt64},
{`"18446744073709551615"`, math.MaxUint64},
} {
have := new(Decimal)
if err := have.UnmarshalJSON([]byte(tc.input)); err != nil {
t.Errorf("input %q triggered error: %v", tc.input, err)
}
if uint64(*have) != tc.want {
t.Errorf("input %q, have %d want %d", tc.input, *have, tc.want)
}
}
}