JSON.stringify() は JavaScript の値を JSON 文字列に変換します —— リクエストボディに入れたり、ファイルに保存したり、localStorage に格納したりするのに使います。シンプルに見えますが、3 つの引数、特殊値の扱い、toJSON フックは開発者を頻繁につまずかせます。本ガイドでは JSON.stringify() のすべて、他言語での同等物、避けるべき落とし穴を扱います。
JSON.stringify の動作
値を再帰的に走査し、仕様準拠の JSON 文字列を生成します。デフォルト出力はコンパクトで余分な空白はありません:
const user = { name: "Ada", age: 36, active: true };
JSON.stringify(user);
// '{"name":"Ada","age":36,"active":true}'常に妥当な JSON を出力するので、JSON 文字列を手で組み立てるべきではありません —— concat やテンプレートリテラルでの構築は [object Object] エラー や 末尾カンマエラー の最大の原因です。
3 つの引数
JSON.stringify(value, replacer, space) は値に加えて、多くの開発者が決して使わない 2 つのオプション引数を取ります —— が、実は強力です。
space —— pretty-printing
第三引数がインデントを制御。スペース数の数値、または '\t' のような文字列を渡します:
JSON.stringify(user, null, 2);
// {
// "name": "Ada",
// "age": 36,
// "active": true
// } コードで JSON を美化する方法そのものです —— How to Format JSON を参照。引数を省略(または 0 を渡す)と minify;How to Minify JSON を参照。
replacer —— フィルタと変換
第二引数は含める キーの配列、または各値を変換する関数です:
// 許可リスト:これらのキーのみ残す
JSON.stringify(user, ['name', 'active']);
// '{"name":"Ada","active":true}'
// 関数:あるフィールドをマスク、別を捨てる
JSON.stringify(
{ name: "Ada", password: "secret", token: "abc" },
(key, value) => {
if (key === 'password') return '[REDACTED]';
if (key === 'token') return undefined; // undefined を返すとキーは省略
return value;
},
);
// '{"name":"Ada","password":"[REDACTED]"}'toJSON フック
値に toJSON() メソッドがあると、JSON.stringify() はそれを呼び出して戻り値をシリアライズします。Date オブジェクトが自動で ISO 文字列になるのはこのためです:
JSON.stringify({ when: new Date('2026-05-24T00:00:00Z') });
// '{"when":"2026-05-24T00:00:00.000Z"}' ← Date.prototype.toJSON 実行
// 独自 toJSON でカスタムシリアライズ
class Money {
constructor(cents) { this.cents = cents; }
toJSON() { return (this.cents / 100).toFixed(2); }
}
JSON.stringify({ price: new Money(1999) });
// '{"price":"19.99"}'落とされる/変換されるもの
JSON には 6 つの型しかないので、JSON 対応のない JavaScript 値は黙って捨てられるか強制変換されます —— ラウンドトリップバグの定番の原因です:
| JavaScript 値 | JSON.stringify の結果 |
|---|---|
undefined(オブジェクト内) | キーが省略 |
undefined(配列内) | null |
| 関数 | 省略(オブジェクト) / null(配列) |
Symbol | 省略 |
NaN、Infinity | null |
Date | ISO 文字列(toJSON 経由) |
BigInt | TypeError を投げる |
JSON と JavaScript オブジェクトの違いの完全リストは JSON vs JavaScript objects。
よくある落とし穴
循環参照はスローする
const a = {};
a.self = a;
JSON.stringify(a);
// TypeError: Converting circular structure to JSON
// 修復:見たオブジェクトを追跡する replacer、またはデータ構造の再設計BigInt はサポートされない
JSON.stringify({ id: 9007199254740993n });
// TypeError: Do not know how to serialize a BigInt
// 修復:先に文字列化、または replacer を追加
JSON.stringify({ id: 9007199254740993n }, (k, v) =>
typeof v === 'bigint' ? v.toString() : v
);大きな整数はラウンドトリップで精度を失う
253 を超える数値は正確に表現できません。大きな整数 ID を stringify して後で parse すると値が変わるかもしれません。そうした ID は文字列で保管してください。
近接 API:structuredClone、reviver、Stable Stringify
structuredClone—— メモリ内の深いコピーにはJSON.parse(JSON.stringify(x))を使わないでください。structuredCloneはネイティブでDate、Map、Set、ArrayBuffer、循環参照を扱い、はるかに高速です。JSON.parseのreviver引数 はここでのreplacerと対称。JSON がモデル化しない型の無損ラウンドトリップが必要なら、ペアで使ってください —— 例えばreplacerでDateを ISO 文字列にエンコードし、reviverで復元。- Stable-stringify ライブラリ(例:
json-stable-stringify、fast-json-stable-stringify)—— キーの挿入順に関わらず同じ文字列を出します。出力がハッシュ化、署名、テキスト比較されるときに使ってください(正式版は RFC 8785 / JCS)。
他言語での Stringify
# Python
import json
json.dumps({"name": "Ada"}) # コンパクト
json.dumps({"name": "Ada"}, indent=2) # 美化
json.dumps({"name": "Ada"}, separators=(',', ':')) # minify
// Go
import "encoding/json"
b, _ := json.Marshal(map[string]string{"name": "Ada"})
// Ruby
require 'json'
{ name: "Ada" }.to_jsonブラウザで JSON を Stringify
JSON 値を文字列リテラルにエスケープしたい —— コード、DB カラム、シェルコマンドに埋め込むため?fixjson の JSON Stringify ツール が即座に、ブラウザで、サーバへ何も送らずに処理します。
よくある質問
JSON.stringify で pretty-print するには?
第三引数を渡す:JSON.stringify(value, null, 2) で 2 スペース、または '\t' でタブ。How to Format JSON。
なぜ JSON.stringify がプロパティを落とすのですか?
undefined、関数、Symbol のプロパティは JSON に表現がないため省略されます。replacer を使うか、先に変換してください。
BigInt を含む値を stringify するには?
JSON.stringify() は BigInt でスローします。bigint 値に .toString() を呼ぶ replacer を提供し、もう一方で意図的に parse し戻してください。
JSON.stringify と JSON.parse の違いは?
stringify は値を JSON 文字列に、parse は JSON 文字列を値に戻します。互いに逆です。パースの落とし穴は Handling broken JSON in JavaScript。
Map や Set を JSON.stringify するには?
そのままでは両方とも "{}" になります —— Map には列挙可能な自身のプロパティが無く、Set は空オブジェクトに stringify されま す。先に JSON フレンドリな形に変換してください(または replacer で):
// Map → [key, value] ペアの配列(ラウンドトリップ可)
JSON.stringify([...myMap]);
// または replacer で:
JSON.stringify({ data: myMap }, (k, v) =>
v instanceof Map ? Object.fromEntries(v) :
v instanceof Set ? [...v] : v
); 戻すときは JSON.parse の reviver で new Map(arr) / new Set(arr) で再構築。素の JSON に Map/Set 型は無いためです。
今すぐ試す
- JSON Stringify —— JSON 値をブラウザで文字列リテラルにエスケープ
- How to Format JSON ——
space引数で pretty-print - How to Minify JSON —— コンパクト形式と意義
- JSON とは? —— stringify が生成できる 6 つの型