Issue
json.Unmarshal unmarshals integers values into float64 when target type is of type interface{}.
Expected behavior
If a json literal is assignable to an integer without losing precision the json.Unmarshal must convert to int64 instead of float64
The problem is located in json/decode.go in convertNumber function:
func (d *decodeState) convertNumber(s string) (interface{}, error) {
if d.useNumber {
return Number(s), nil
}
f, err := strconv.ParseFloat(s, 64) // See here! By default it converts to Float
if err != nil {
return nil, &UnmarshalTypeError{"number " + s, reflect.TypeOf(0.0), int64(d.off)}
}
return f, nil
}
by default it does strconv.ParseFloat
Steps to Reproduce
func TestUnmarshalNumber(t *testing.T) {
var v interface{}
exp := int64(1621867181)
err := json.Unmarshal([]byte(`1621867181`), &v)
require.NoError(t, err)
require.IsType(t, exp, v)
}
Error:
=== RUN TestUnmarshalNumber
token_test.go:502:
Error Trace: token_test.go:502
Error: Object expected to be of type int64, but was float64
Test: TestUnmarshalNumber
--- FAIL: TestUnmarshalNumber (0.00s)
FAIL
FAIL token/jwt 0.025s
Proposed Solution
convertNumber should try first strconv.ParseInt and in case of err it does strconv.ParseFloat
If you agree with the proposal I can submit a PR