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
valueis not a string; - Consider
BigIntliteral values with or without "n", and exclude "n" from the string if it exists; - Return any non-numeric values unchanged;
- Convert number to:
BigIntif it exceeds the safe integer range (Number.MIN_SAFE_INTEGER-Number.MAX_SAFE_INTEGER), or;Numberif 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.