Skip to content
This repository was archived by the owner on Feb 27, 2023. It is now read-only.
This repository was archived by the owner on Feb 27, 2023. It is now read-only.

json.Unmarshal converts json literal integer to float64 instead of int64 when taget type is of type interface{} #351

@narg95

Description

@narg95

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions