JSON.parse() と JSON.stringify()

JSON との変換で何が消え、何が形を変えるのかをまとめます。undefined や Map が黙って落ちる理由、循環参照で例外になる条件、reviver と toJSON の使い方を実行して確かめます。

実行して検証済み処理系Node 22.23.3対応ES5難易度●●○○○目安 約10分更新

JSON.stringify() は値を文字列にし、JSON.parse() は文字列を値に戻します。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{"name":"あ","n":1,"ok":true,"list":[1,2]} { a: 1 }
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{ "a": 1, "b": [ 2 ] }

第3引数を渡すと、読みやすく字下げされます。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{"n":null,"i":null,"d":"2026-09-08T00:00:00.000Z","m":{}}
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{"a":1} [1,null,2]

人が読むときだけ使ってください。 通信量が増えます。

黙って消えるもの

ここがいちばん事故になります。 例外は出ません。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
undefined undefined undefined
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
TypeError TypeError
入れたもの どうなるか
undefined 鍵ごと消える
関数 鍵ごと消える
Symbol 鍵ごと消える
NaN / Infinity null
Date 文字列になる(戻すと Date ではない)
Map / Set 空のオブジェクト

JSON にはこれらを表す書き方がありません。JSON は JavaScript の一部ではないからです。

配列の中では、消えるかわりに null になります。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
SyntaxError SyntaxError SyntaxError
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{ ok: true, value: { a: 1 } } { ok: false, value: null }

配列は長さを保たないといけないので、詰められずに null が入ります。

戻り値が文字列とは限らない

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
1 あ true null "あ"
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{"price":"300円"}

文字列ではなく undefined が返ります。 JSON.stringify(値).length のような書き方は、ここで落ちます。

例外になるもの

消えずに例外を投げるものが2つあります。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{"a":1} {"a":1}
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
true 2026-09-08T00:00:00.000Z
  • 循環参照(自分を含む構造)
  • BigInt

例外の文言は処理系によって違います。ここでは種類(name)だけを見ています。

読めない文字列は SyntaxError

javascript
const src = { d: new Date('2026-09-08'), u: undefined };
const copy = JSON.parse(JSON.stringify(src));

console.log(typeof copy.d);
console.log('u' in copy);
string false
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
true true

JSON は JavaScript のオブジェクトリテラルより厳しい決まりです。

JavaScript では書ける JSON では
{ 'a': 1 } 単引用符は不可
{ a: 1 } 引用符なしの鍵は不可
{ "a": 1, } 末尾のカンマは不可
// コメント コメントは不可

文言と読み方は、エラーのページで詳しく扱っています。 → SyntaxError: Unexpected token

外から来た文字列は、必ず try で囲んでください。

オブジェクト以外も扱える

JSON はオブジェクトだけの形式ではありません。

文字列を stringify() すると、引用符が付いた文字列になります。 二重に変換して引用符が増えるのは、よくある間違いです。

変換のしかたを変える

toJSON() を持たせる

オブジェクト側に toJSON() があれば、その戻り値が使われます。

Date が文字列になるのも、Date が toJSON() を持っているからです。

第2引数で選ぶ・変える

配列を渡せばその鍵だけ、関数を渡せば値を書き換えられます。 undefined を返すと、その鍵は出力されません。

パスワードやトークンを外す用途に使えます。

読み込むときに戻す

JSON.parse() の第2引数(reviver)で、値を作り直せます。

よくある間違い

深い複製に使う

複製はできます。ですが中身が変わります。 Date は文字列になり、undefined の鍵は消えます。

structuredClone() を使ってください。

→ オブジェクトを結合する

鍵の順番を当てにする

JSON.stringify() は、オブジェクトの鍵の順をそのまま出します。 ですがオブジェクトの鍵の順は、整数に見える鍵が先に来ます。

文字列を比べて同じかどうか判定する用途(署名・キャッシュの鍵)では、 順番の違いで別物と判定されます。鍵を並べ替えてから変換してください。

まとめ

  • undefined / 関数 / Symbol は黙って消える。配列の中では null
  • NaN と Infinity は null。Map / Set は {}
  • 循環参照と BigInt は例外
  • JSON.stringify() は文字列以外を返すことがある(undefined)
  • 外から来た文字列は必ず try で囲む
  • 深い複製には使わない。 structuredClone() を使う

この記事の根拠

  1. The JSON Object — ECMAScript® 2026 Language Specificationtc39.es
  2. RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Formatwww.rfc-editor.org
  3. JSON.stringify — MDNdeveloper.mozilla.org

掲載しているコード例は、公開前に読み手が押したときに動くのと同じもので実行して出力を突き合わせています。結果はリポジトリに残しています。

このページの原文(Markdown)