From 84648d393a60832e6ebfd991918da0432b29be0a Mon Sep 17 00:00:00 2001 From: gufeijun Date: Thu, 10 Nov 2022 18:37:28 +0800 Subject: [PATCH] fix: solve precision problem when decode bigint in json --- stdlib/json/decode.go | 16 ++++++++++++---- stdlib/json/json_test.go | 2 ++ stdlib/json_test.go | 8 ++++---- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/stdlib/json/decode.go b/stdlib/json/decode.go index 6d468ef0..37432d41 100644 --- a/stdlib/json/decode.go +++ b/stdlib/json/decode.go @@ -62,9 +62,12 @@ func (d *decodeState) scanNext() { // scanWhile processes bytes in d.data[d.off:] until it // receives a scan code not equal to op. -func (d *decodeState) scanWhile(op int) { +func (d *decodeState) scanWhile(op int) (isFloat bool) { s, data, i := &d.scan, d.data, d.off for i < len(data) { + if data[i] == '.' { + isFloat = true + } newOp := s.step(s, data[i]) i++ if newOp != op { @@ -76,6 +79,7 @@ func (d *decodeState) scanWhile(op int) { d.off = len(data) + 1 // mark processed EOF with len+1 d.opcode = d.scan.eof() + return } func (d *decodeState) value() (tengo.Object, error) { @@ -185,7 +189,7 @@ func (d *decodeState) object() (tengo.Object, error) { func (d *decodeState) literal() (tengo.Object, error) { // All bytes inside literal return scanContinue op code. start := d.readIndex() - d.scanWhile(scanContinue) + isFloat := d.scanWhile(scanContinue) item := d.data[start:d.readIndex()] @@ -210,8 +214,12 @@ func (d *decodeState) literal() (tengo.Object, error) { if c != '-' && (c < '0' || c > '9') { panic(phasePanicMsg) } - n, _ := strconv.ParseFloat(string(item), 10) - return &tengo.Float{Value: n}, nil + if isFloat { + n, _ := strconv.ParseFloat(string(item), 10) + return &tengo.Float{Value: n}, nil + } + n, _ := strconv.ParseInt(string(item), 10, 64) + return &tengo.Int{Value: n}, nil } } diff --git a/stdlib/json/json_test.go b/stdlib/json/json_test.go index 5abfdec2..b12bd64c 100644 --- a/stdlib/json/json_test.go +++ b/stdlib/json/json_test.go @@ -57,6 +57,8 @@ func TestJSON(t *testing.T) { "arr": ARR{1, 2, 3, "four"}}) testJSONEncodeDecode(t, MAP{"a": 0, "b": "bee", "arr": ARR{1, 2, 3, MAP{"a": false, "b": 109.4}}}) + + testJSONEncodeDecode(t, MAP{"id1": 7075984636689534001, "id2": 7075984636689534002}) } func TestDecode(t *testing.T) { diff --git a/stdlib/json_test.go b/stdlib/json_test.go index adf7037c..ac8dcf19 100644 --- a/stdlib/json_test.go +++ b/stdlib/json_test.go @@ -48,13 +48,13 @@ func TestJSON(t *testing.T) { expect([]byte("[[\"bar\",1],[\"bar\",1]]")) module(t, "json").call("decode", `5`). - expect(5.0) + expect(5) module(t, "json").call("decode", `"foo"`). expect("foo") module(t, "json").call("decode", `[1,2,3,"bar"]`). - expect(ARR{1.0, 2.0, 3.0, "bar"}) + expect(ARR{1, 2, 3, "bar"}) module(t, "json").call("decode", `{"foo":5}`). - expect(MAP{"foo": 5.0}) + expect(MAP{"foo": 5}) module(t, "json").call("decode", `{"foo":2.5}`). expect(MAP{"foo": 2.5}) module(t, "json").call("decode", `{"foo":true}`). @@ -62,7 +62,7 @@ func TestJSON(t *testing.T) { module(t, "json").call("decode", `{"foo":"bar"}`). expect(MAP{"foo": "bar"}) module(t, "json").call("decode", `{"foo":[1,2,3,"bar"]}`). - expect(MAP{"foo": ARR{1.0, 2.0, 3.0, "bar"}}) + expect(MAP{"foo": ARR{1, 2, 3, "bar"}}) module(t, "json"). call("indent", []byte("{\"foo\":[\"bar\",1,1.8,56,true]}"), "", " ").