← 記事一覧

JSON.stringify で JSON を文字列化する方法

JSON.stringify は値を JSON 文字列に変換します。space と replacer 引数、toJSON フック、暗黙に落とされたり例外になる値について学びます。

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省略
NaNInfinitynull
DateISO 文字列(toJSON 経由)
BigIntTypeError を投げる

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:structuredClonereviver、Stable Stringify

  • structuredClone —— メモリ内の深いコピーには JSON.parse(JSON.stringify(x)) を使わないでください。structuredClone はネイティブで DateMapSetArrayBuffer、循環参照を扱い、はるかに高速です。
  • JSON.parsereviver 引数 はここでの replacer と対称。JSON がモデル化しない型の無損ラウンドトリップが必要なら、ペアで使ってください —— 例えば replacerDate を ISO 文字列にエンコードし、reviver で復元。
  • Stable-stringify ライブラリ(例:json-stable-stringifyfast-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 型は無いためです。

今すぐ試す