To parse a large number in a JSON string without losing precision, you can transform it to BigInt
by specifying a reviver function as the second argument to JSON.parse()
.
Syntax
JSON.parse(json, reviverFn)
The reviver
function is called with the following two arguments:
key
— the key associated with the value being parsed;value
— the parsed value.
Implementation
You can use the reviver
function to define how to deal with large numbers and convert them to BigInt
, for example, in the following steps:
- Return early if
value
is not a string; - Consider
BigInt
literal values with or without "n
", and exclude "n
" from the string if it exists; - Return any non-numeric values unchanged;
- Convert number to:
BigInt
if it exceeds the safe integer range (Number.MIN_SAFE_INTEGER
-Number.MAX_SAFE_INTEGER
), or;Number
if it's within safe integer range.
Code
// ES10+
const bigIntReviver = (key, value) => {
// 1: return early if `value` is not a string
if (typeof value !== 'string') {
return value;
}
// 2.1: Consider `BigInt` values with or without 'n
'
// 2.2: Exclude `n` from the end of string, if it exists
const match = /^(-?\d+)n?$/.exec(value);
// 3: return non-numeric values unchanged
if (!match) {
return value;
}
const numericValue = match[1];
// 4.1: Convert to `BigInt` if value exceeds safe integer range
if (BigInt(numericValue) > Number.MAX_SAFE_INTEGER || BigInt(numericValue) < Number.MIN_SAFE_INTEGER) {
return BigInt(numericValue);
}
// 4.2: Convert to `Number` if value is within safe integer range
return Number(numericValue);
};
Examples
The custom bigIntReviver
reviver function should handle cases where the JSON string represents a BigInt literal with or without the "n
" at the end:
// ES10+ // case 1: negative/positive numeric values exceeding safe range console.log(JSON.parse('{"num":"9223372036854775807000n"}', bigIntReviver)); // {num: 9223372036854775807000n} console.log(JSON.parse('{"num":"-18014398509481982n"}', bigIntReviver)); // {num: -18014398509481982n} console.log(JSON.parse('{"num":"9223372036854775807000"}', bigIntReviver)); // {num: 9223372036854775807000n} console.log(JSON.parse('{"num":"-18014398509481982"}', bigIntReviver)); // {num: -18014398509481982n} // case 2: negative/positive numeric values in safe range console.log(JSON.parse('{"num":"1234n"}', bigIntReviver)); // {num: 1234} console.log(JSON.parse('{"num":"-1234n"}', bigIntReviver)); // {num: -1234} console.log(JSON.parse('{"num":"0n"}', bigIntReviver)); // {num: 0} console.log(JSON.parse('{"num":"-0n"}', bigIntReviver)); // {num: -0} console.log(JSON.parse('{"num":"1234"}', bigIntReviver)); // {num: 1234} console.log(JSON.parse('{"num":"-1234"}', bigIntReviver)); // {num: -1234} console.log(JSON.parse('{"num":"0"}', bigIntReviver)); // {num: 0} console.log(JSON.parse('{"num":"-0"}', bigIntReviver)); // {num: -0}
The "n
" at the end of a number merely suggests that the number is a bigint primitive.
This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.