diff --git a/lib/parse.js b/lib/parse.js index 84d142f..af5556b 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -206,21 +206,29 @@ var json_parse = function (options) { error('Bad number'); } else { if (BigNumber == null) BigNumber = require('bignumber.js'); - if (Number.isSafeInteger(number)) - return !_options.alwaysParseAsBig - ? number - : _options.useNativeBigInt - ? BigInt(number) - : new BigNumber(number); - else - // Number with fractional part should be treated as number(double) including big integers in scientific notation, i.e 1.79e+308 - return _options.storeAsString - ? string - : /[\.eE]/.test(string) - ? number - : _options.useNativeBigInt - ? BigInt(string) - : new BigNumber(string); + + if (Number.isSafeInteger(number)) { + return _options.alwaysParseAsBig + ? (_options.useNativeBigInt ? BigInt(number) : new BigNumber(number)) + : number; + } + + // If the number has a decimal or exponential part, it can't be + // represented as BigInt, not always. + if (/[\.eE]/.test(string)) { + if (_options.storeAsString) { + const exponent = Math.floor(Math.log2(Math.abs(number))); + if (exponent > 53) { + return string; + } + } + return number; + } + + // Remaining cases: large integers + return _options.storeAsString + ? string + : (_options.useNativeBigInt ? BigInt(string) : new BigNumber(string)); } }, string = function () { diff --git a/test/bigint-parse-test.js b/test/bigint-parse-test.js index 4156b3e..c97f71f 100644 --- a/test/bigint-parse-test.js +++ b/test/bigint-parse-test.js @@ -71,4 +71,26 @@ describe("Testing native BigInt support: parse", function () { expect(output).to.equal(input); done(); }); + + it("Should show JSONbig parses decimal numbers as numbers, not strings", function (done) { + var JSONbig = require('../index')({ + "storeAsString": true + }); + var input = '{"testNumber": 95.45454545454545}'; + var obj = JSONbig.parse(input); + expect(obj.testNumber.toString(), "test number").to.equal("95.45454545454545"); + expect(typeof obj.testNumber, "test number").to.equal('number'); + done(); + }); + + it("Should show JSONbig parses large decimal numbers as strings when storeAsString is true", function (done) { + var JSONbig = require('../index')({ + "storeAsString": true + }); + var input = '{"largeDecimal": 100000000000000000001.23}'; + var obj = JSONbig.parse(input); + expect(obj.largeDecimal, "large decimal number").to.equal("100000000000000000001.23"); + expect(typeof obj.largeDecimal, "large decimal number").to.equal('string'); + done(); + }); }); \ No newline at end of file