LoginSignup
3
0

More than 3 years have passed since last update.

JSON に記述された数値型の範囲外の整数値を JavaScript でパースする

Last updated at Posted at 2020-12-15

JavaScript の数値型が確実に扱える整数値の範囲は -9007199254740991 〜 9007199254740991

確実に使用できる整数値の範囲は最小値 Number.MIN_SAFE_INTEGER から最大値 Number.MAX_SAFE_INTEGER の間となる。それを超える値は処理系による。

Number - JavaScript | MDN

const biggestInt = Number.MAX_SAFE_INTEGER // (253 - 1) => 9007199254740991
const smallestInt = Number.MIN_SAFE_INTEGER // -(253 - 1) => -9007199254740991

JSON にシリアライズされたデータを解析する場合、整数値がこの範囲を超えていると、 JSON パーサーがこの値を Number 型に変換したときに信頼できない値になります。
可能な回避策として、代わりに String を使用してください。
大きい数値は BigInt 型を用いて表すことができます。

json-bigint ライブラリを使うと Number 型の範囲外の値をパースできる

json-bigint - npm

JSON.parse/stringify with bigints support. Based on Douglas Crockford JSON.js package and bignumber.js library.

サンプルコード

今回の検証環境: macOS Catalina + Node.js v14.15.1 + json-bigint 1.0.0

$ node --version
v14.15.1

読み込む JSON ファイル (data.json)。
Number.MIN_SAFE_INTEGER (-9007199254740991) と Number.MAX_SAFE_INTEGER (9007199254740991) を超える値を記述している。

{
  "under3": -99999999999999999,
  "under2": -9999999999999999,
  "under1": -9007199254740992,
  "min":    -9007199254740991,
  "max":     9007199254740991,
  "over1":   9007199254740992,
  "over2":   9999999999999999,
  "over3":   99999999999999999
}

標準ライブラリの JSON を使用した場合

ソースコード (json-parse.js)。

console.log(`整数の最小値: ${Number.MIN_SAFE_INTEGER}`);
console.log(`整数の最大値: ${Number.MAX_SAFE_INTEGER}`);

const fs = require('fs');
const data = JSON.parse(fs.readFileSync('data.json'));
console.log('under3:'  + data.under3);
console.log('under2:'  + data.under2);
console.log('under1:'  + data.under1);
console.log('min:   '  + data.min);
console.log('max:    ' + data.max);
console.log('over1:  ' + data.over1);
console.log('over2:  ' + data.over2);
console.log('over3:  ' + data.over3);

実行結果。
under1 と over1 は確実に使用できる値の範囲外ではあるが正確な値が出力された。
under3, under2, over2, over3 は不正確な値になってしまった。

$ node json-parse.js
整数の最小値: -9007199254740991
整数の最大値: 9007199254740991
under3:-100000000000000000
under2:-10000000000000000
under1:-9007199254740992
min:   -9007199254740991
max:    9007199254740991
over1:  9007199254740992
over2:  10000000000000000
over3:  100000000000000000

json-bigint を使用した場合

ソースコード (json-bigint.js)。

console.log(`整数の最小値: ${Number.MIN_SAFE_INTEGER}`);
console.log(`整数の最大値: ${Number.MAX_SAFE_INTEGER}`);

const fs = require('fs');
const JSONbig = require('json-bigint');
const data = JSONbig.parse(fs.readFileSync('data.json'));
console.log('under3:'  + data.under3);
console.log('under2:'  + data.under2);
console.log('under1:'  + data.under1);
console.log('min:   '  + data.min);
console.log('max:    ' + data.max);
console.log('over1:  ' + data.over1);
console.log('over2:  ' + data.over2);
console.log('over3:  ' + data.over3);

実行結果。
確実に使用できる値の範囲外でも正確な値が出力されている。

$ node json-bigint.js
整数の最小値: -9007199254740991
整数の最大値: 9007199254740991
under3:-99999999999999999
under2:-9999999999999999
under1:-9007199254740992
min:   -9007199254740991
max:    9007199254740991
over1:  9007199254740992
over2:  9999999999999999
over3:  99999999999999999

参考資料

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0