LoginSignup
15
1

More than 1 year has passed since last update.

JSONでBigIntがうまく扱えないのなんで?

Posted at

はじめに

でかい数字をJSONで表現するとどうなるんだろう

// number
> JSON.stringify({ "a": 911232123123127987297})
'{"a":911232123123128000000}'
> JSON.parse(`{ "a": 911232123123127987297}`)
{ a: 911232123123128000000 }

// BigInt
> JSON.stringify({ "a": 911232123123127987297n})
Uncaught TypeError: Do not know how to serialize a BigInt
    at JSON.stringify (<anonymous>)
    at <anonymous>:2:6
> JSON.parse(`{ "a": 911232123123127987297n}`)
Uncaught SyntaxError: Expected ',' or '}' after property value in JSON at position 28
    at JSON.parse (<anonymous>)
    at <anonymous>:2:6

Do not know how to serialize a BigInt :thinking:

なんかBigIntはうまく扱えないようです。なんででしょ

BigIntについて

MDNみるのが一番良い。

JSONのくだりも書いてある

JSON.stringify() を BigInt 値に対して使用すると TypeError が発生します。 BigInt 値は既定で JSON のシリアライズに対応していないためです。ただし、 replacer 引数を JSON.stringify で使用すると、 BigInt のプロパティをエラーなしでシリアライズすることができます。

長整数になる値が含まれると思われる JSON データがある場合は、 reviver 引数を JSON.parse で使用することで取り扱うことができます。

なんで自分でパースとシリアライズ定義時にいちいち変換かけないかんの?

JSONでのBigIntサポートは議論されたが互換性が優先された

要点絞ると

という大激論の末、BigIntはJSONでうまく扱われない子になってしまったようです

JSONでBigIntを扱えるようにしようとする活動もろもろ

JSOX

J-SOXと似ててググらビリティが悪い。jsonxっていう全然用途が違うものもあるので注意

JSON5/JSON6 といった拡張JSONフォーマットを提案している方がBigInt対応も考慮した拡張JSONフォーマットとして定義
プロポーザル的な立ち位置でJSON拡張フォーマットとしてBigIntをうまく扱えるようにしようとしている

import { JSOX } from "npm:jsox"

const bigintObj = { a: 8982979873927987392837212139794n }

console.log(JSOX.stringify(bigintObj))
// {a:8982979873927987392837212139794n}
console.dir(JSOX.parse(JSOX.stringify(bigintObj)))
// { a: 8982979873927987392837212139794n }

jsoxは n 表記でシリアライズされるしパースするとちゃんとBigIntとして扱う

json-bigint

JSONbig.parse, JSONbig.stringify といったネームスペースが増える

ただし2年くらい更新止まってる

json-bigint-native

前述の json-bigint をフォークして作っていて比較的手も入ってる

import JSONbig from "npm:json-bigint-native"

const bigintObj = { a: 8982979873927987392837212139794n }

console.log(JSONbig.stringify(bigintObj))
// {"a":8982979873927987392837212139794}
console.dir(JSON.parse(JSONbig.stringify(bigintObj)))
// { a: 8.982979873927987e+30 }

シリアライズした結果は 123n じゃなくてそのままでかいDigitが入る
パースすると指数表記なんでnumberになっているっぽい

余談 - JSONの拡張フォーマット色々

JSONC

コメントが書けるJSON

VSCodeの設定とかはこれ

JSON-Scheme

JSONに型情報を持ち込むやつ

CBOR/BSON

JSONをバイナリで表現しようぜのやつ

CBOR

BSON

15
1
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
15
1