3秒でわかる
JavaScriptの値をJSON文字列へ変換する組み込み関数。通信や保存の直前で必ず通る変換で、消える値の癖を知る必要があります。
もう少し詳しく
どういうものか
JSON.stringify は、JavaScriptのオブジェクトや配列をJSON形式の文字列へ変換する組み込み関数です。第2引数に置き換え用の関数や残したいキーの配列、第3引数に字下げ幅を渡せます。逆向きの変換は JSON.parse が担当します。
なぜ必要か
ネットワークやlocalStorageが扱えるのはバイト列と文字列だけで、メモリ上のオブジェクトをそのまま送ることはできません。そこで、構造を保ったまま文字列へ直す共通の書式としてJSONが使われます。fetchでPOSTするとき、保存するとき、ログへ構造を残すときに、この関数が変換の役割を負います。
具体例
const user = { id: 1, name: "田中", tags: ["新規"], joined: new Date("2024-04-01") };
JSON.stringify(user);
// {"id":1,"name":"田中","tags":["新規"],"joined":"2024-04-01T00:00:00.000Z"}
JSON.stringify(user, ["id", "name"]); // {"id":1,"name":"田中"}
JSON.stringify(user, null, 2); // 2 スペース字下げで読みやすく整形
// 消える値の例
JSON.stringify({ a: undefined, b: () => 1, c: NaN, d: 3n === undefined });
// {"c":null} ← undefined と関数はキーごと消え、NaN は null になるつまずきやすいところ
まず、undefined と関数はオブジェクトのプロパティだと丸ごと消え、配列の要素だと null に化けます。次に、Date は文字列になるため、JSON.parse で戻しても Date には復元されません。日付を含むデータを往復させるときは復元処理を自分で書きます。NaN や Infinity は null になり、BigInt は例外を投げます。そして循環参照があるオブジェクトは TypeError で止まります。
また、オブジェクトの比較に使うのは危険です。キーの並び順が違うだけで別の文字列になるため、JSON.stringify(a) === JSON.stringify(b) は等価判定として当てになりません。
似た用語との違い
| 関数 | 向き | 失敗のしかた |
|---|---|---|
| JSON.stringify | 値から文字列へ | 循環参照やBigIntで例外 |
| JSON.parse | 文字列から値へ | 壊れた文字列で例外 |
| structuredClone | 値から値へ複製 | 関数を含むと例外 |