1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
|
---
title: JSON.stringify()
slug: Web/JavaScript/Reference/Global_Objects/JSON/stringify
tags:
- JSON
- JavaScript
- Method
- Objects
- Reference
- stringify
translation_of: Web/JavaScript/Reference/Global_Objects/JSON/stringify
---
<div>{{JSRef}}</div>
<p><strong><code>JSON.stringify()</code></strong> メソッドは、ある JavaScript のオブジェクトや値を JSON 文字列に変換します。置き換え関数を指定して値を置き換えたり、置き換え配列を指定して指定されたプロパティのみを含むようにしたりすることもできます。</p>
<div>{{EmbedInteractiveExample("pages/js/json-stringify.html")}}</div>
<p class="hidden">この対話型サンプルのソースファイルは GitHub リポジトリに格納されています。対話型サンプルプロジェクトに協力したい場合は、 <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> をクローンしてプルリクエストを送信してください。</p>
<h2 id="Syntax" name="Syntax">構文</h2>
<pre class="syntaxbox notranslate">JSON.stringify(<var>value</var>[, <var>replacer</var>[, <var>space</var>]])</pre>
<h3 id="Parameters" name="Parameters">引数</h3>
<dl>
<dt><code><var>value</var></code></dt>
<dd>JSON 文字列に変換する値です。</dd>
<dt><code><var>replacer</var></code> {{optional_inline}}</dt>
<dd>文字列化の手順の挙動を変更する関数、または値のオブジェクトを JSON 文字列に含めるプロパティを選択する許可リストとして機能する {{JSxRef("String")}} と {{JSxRef("Number")}} の配列。もしこの値が {{JSxRef("null")}} であるか提供されなかった場合は、結果の文字列にオブジェクトのすべてのプロパティが含まれます。</dd>
<dt><code><var>space</var></code> {{optional_inline}}</dt>
<dd>出力する JSON 文字列に可読性を目的に空白を挿入するために使う {{JSxRef("String")}} または {{JSxRef("Number")}} オブジェクトです。
<p>これが <code>Number</code> のときは、空白として使う空白文字の数を示します。この数の上限は10です (それより大きい数値は、単に <code>10</code> となります)。 1 より小さい値は空白を使わないことを示します。</p>
<p>これが <code>String</code> のときは、その文字列 (10文字より長い場合はその最初の10文字) が空白として使われます。もしこの引数が提供されない (または null である) 場合は、空白は使用されません。</p>
</dd>
</dl>
<h3 id="Return_value" name="Return_value">返値</h3>
<p>与えられた値を表現する JSON 文字列。</p>
<h3 id="Exceptions" name="Exceptions">例外</h3>
<ul>
<li>{{JSxRef("TypeError")}} ("cyclic object value") 例外は、循環参照が見つかった時に発生します。</li>
<li>{{JSxRef("TypeError")}} ("BigInt value can't be serialized in JSON") 例外は、 {{JSxRef("BigInt")}} 値を文字列化しようとしたときに発生します。</li>
</ul>
<h2 id="Description" name="Description">説明</h2>
<p><code>JSON.stringify()</code> は値をそれを表す JSON 表記に変換します。</p>
<ul>
<li>値が <code><a href="#toJSON_behavior">toJSON()</a></code> メソッドを持っている場合は、データがどのようにシリアライズされるかを定義する必要があります。</li>
<li>{{JSxRef("Boolean")}}、 {{JSxRef("Number")}}、 {{JSxRef("String")}} の各オブジェクトは、文字列化の際に慣習的な変換セマンティクスに従い、対応するプリミティブ値に変換されます。</li>
<li>{{JSxRef("undefined")}}、 関数 ({{JSxRef("Function")}})、シンボル ({{JSxRef("Symbol")}}) は有効な JSON 値ではありません。変換中にそのような値に遭遇した場合は、 (オブジェクトの中で発見された場合は) 省略されたり、 (配列の中で見つかった場合は) {{JSxRef("null")}} に変換されたりします。 <code>JSON.stringify</code> は <code>JSON.stringify(function(){})</code> や <code>JSON.stringify(undefined)</code> のように「純粋」な値を渡した場合に <code>undefined</code> を返すことがあります。</li>
<li>シンボル ({{JSxRef("Symbol")}}) がキーとなっているプロパティはすべて、 <code><var>replacer</var></code> 関数を使用する場合でも完全に無視されます。</li>
<li>{{JSxRef("Date")}} のインスタンスは文字列を返す <code>toJSON()</code> を実装しています (<code>date.toISOString()</code> と同じです)。したがって、これらは文字列として扱われます。</li>
<li>{{JSxRef("Infinity")}} および {{JSxRef("NaN")}} の数値は、 {{JSxRef("null")}} の値と同様、すべて <code>null</code> と見なされます。</li>
<li>その他のすべての {{JSxRef("Object")}} のインスタンスは ({{JSxRef("Map")}}, {{JSxRef("Set")}}, {{JSxRef("WeakMap")}}, {{JSxRef("WeakSet")}} を含め)、列挙可能なプロパティのみがシリアライズされます。</li>
</ul>
<h2 id="Examples" name="Examples">例</h2>
<h3 id="Using_JSON.stringify" name="Using_JSON.stringify">JSON.stringify の使用</h3>
<pre class="brush: js notranslate">JSON.stringify({}); // '{}'
JSON.stringify(true); // 'true'
JSON.stringify('foo'); // '"foo"'
JSON.stringify([1, 'false', false]); // '[1,"false",false]'
JSON.stringify([NaN, null, Infinity]); // '[null,null,null]'
JSON.stringify({ x: 5 }); // '{"x":5}'
JSON.stringify(new Date(2006, 0, 2, 15, 4, 5))
// '"2006-01-02T15:04:05.000Z"'
JSON.stringify({ x: 5, y: 6 });
// '{"x":5,"y":6}'
JSON.stringify([new Number(3), new String('false'), new Boolean(false)]);
// '[3,"false",false]'
// 文字列がキーとなった配列要素は列挙可能ではなく、 JSON では意味をなさない
let a = ['foo', 'bar'];
a['baz'] = 'quux'; // a: [ 0: 'foo', 1: 'bar', baz: 'quux' ]
JSON.stringify(a);
// '["foo","bar"]'
JSON.stringify({ x: [10, undefined, function(){}, Symbol('')] });
// '{"x":[10,null,null,null]}'
// 標準データ構造
JSON.stringify([new Set([1]), new Map([[1, 2]]), new WeakSet([{a: 1}]), new WeakMap([[{a: 1}, 2]])]);
// '[{},{},{},{}]'
// 型付き配列
JSON.stringify([new Int8Array([1]), new Int16Array([1]), new Int32Array([1])]);
// '[{"0":1},{"0":1},{"0":1}]'
JSON.stringify([new Uint8Array([1]), new Uint8ClampedArray([1]), new Uint16Array([1]), new Uint32Array([1])]);
// '[{"0":1},{"0":1},{"0":1},{"0":1}]'
JSON.stringify([new Float32Array([1]), new Float64Array([1])]);
// '[{"0":1},{"0":1}]'
// toJSON()
JSON.stringify({ x: 5, y: 6, toJSON(){ return this.x + this.y; } });
// '11'
// シンボル:
JSON.stringify({ x: undefined, y: Object, z: Symbol('') });
// '{}'
JSON.stringify({ [Symbol('foo')]: 'foo' });
// '{}'
JSON.stringify({ [Symbol.for('foo')]: 'foo' }, [Symbol.for('foo')]);
// '{}'
JSON.stringify({ [Symbol.for('foo')]: 'foo' }, function(k, v) {
if (typeof k === 'symbol') {
return 'a symbol';
}
});
// undefined
// 列挙可能でないプロパティ:
JSON.stringify( Object.create(null, { x: { value: 'x', enumerable: false }, y: { value: 'y', enumerable: true } }) );
// '{"y":"y"}'
// BigInt の値は例外が発生
JSON.stringify({x: 2n});
// TypeError: BigInt value can't be serialized in JSON
</pre>
<h3 id="The_replacer_parameter" name="The_replacer_parameter">replacer 引数</h3>
<p><code><var>replacer</var></code> 引数は関数または配列です。</p>
<p><strong>関数の場合</strong>、 <var>key</var> と文字列化される <var>value</var> の2つの引数を取ります。キーをもつオブジェクトが <code><var>replacer</var></code> では <code>this</code> 引数として提供されます。</p>
<p>最初、 <code><var>replacer</var></code> 関数が、文字列化されるオブジェクト自体を表すキーとして空文字列で呼び出されます。それから、文字列化されるオブジェクトのそれぞれのプロパティや配列に対して呼び出されます。</p>
<p>これは、 JSON 文字列に加えるべき値を次のように返します。</p>
<ul>
<li>数値 ({{JSxRef("Number")}}), 文字列 ({{JSxRef("String")}}), 論理値 ({{JSxRef("Boolean")}}), {{JSxRef("null")}} を返すと、その値を文字列化したものがプロパティの値として使用されます。</li>
<li>関数 ({{JSxRef("Function")}}), シンボル ({{JSxRef("Symbol")}}), {{JSxRef("undefined")}} を返すと、出力にはそのプロパティが含まれなくなります。</li>
<li>その他のオブジェクトを返した場合、そのオブジェクトはそれぞれのプロパティに <code><var>replacer</var></code> 関数を呼び出して再帰的に文字列化します。</li>
</ul>
<div class="blockIndicator note">
<p><strong>注:</strong> <code><var>replacer</var></code> 関数を使用して配列から値を削除することはできません。 <code>undefined</code> や関数を返すと、代わりに <code>null</code> が使用されます。</p>
</div>
<div class="blockIndicator note">
<p><strong>注:</strong> <code><var>replacer</var></code> が、オブジェクトが初期状態であるか、空文字列のキーを持つプロパティであるかを判別するには (どちらの場合もキーが空文字列になり、オブジェクトが値になる可能性があるので)、繰り返し回数を追跡しておく必要があります (繰り返しが1回を超えた場合、空文字列のキーであることが分かります)。</p>
</div>
<h4 id="Example_replacer_as_a_function" name="Example_replacer_as_a_function">関数としての replacer の例</h4>
<pre class="brush: js notranslate">function replacer(key, value) {
// Filtering out properties
if (typeof value === 'string') {
return undefined;
}
return value;
}
var foo = {foundation: 'Mozilla', model: 'box', week: 45, transport: 'car', month: 7};
JSON.stringify(foo, replacer);
// '{"week":45,"month":7}'
</pre>
<h4 id="Example_replacer_as_an_array" name="Example_replacer_as_an_array">配列としての replacer の例</h4>
<p><code><var>replacer</var></code> が配列である場合、その配列の値は結果の JSON 文字列に含めるプロパティの名前を示します。</p>
<pre class="brush: js notranslate">JSON.stringify(foo, ['week', 'month']);
// '{"week":45,"month":7}', "week" と "month" プロパティだけが保持される
</pre>
<h3 id="The_space_argument" name="The_space_argument">space 引数</h3>
<p><code>space</code> 引数で最終的な文字列での空白の数を調整できます。</p>
<ul>
<li><strong>数値であれば</strong>、レベルの階層がそれぞれその数の空白文字 (最大10文字) でインデントされます。</li>
<li><strong>文字列であれば</strong>、レベル階層がそれぞれこの文字列 (またはその最初の10文字) でインデントされます。</li>
</ul>
<pre class="brush: js notranslate">JSON.stringify({ a: 2 }, null, ' ');
// '{
// "a": 2
// }'
</pre>
<p>タブ文字を使うと、標準的な表示の整形と同様になります。</p>
<pre class="brush: js notranslate">JSON.stringify({ uno: 1, dos: 2 }, null, '\t');
// returns the string:
// '{
// "uno": 1,
// "dos": 2
// }'
</pre>
<h3 id="toJSON_behavior" name="toJSON_behavior">toJSON() の挙動</h3>
<p>文字列化されるオブジェクトに <code>toJSON</code> という名前の値に関数を持ったプロパティがある場合、その <code>toJSON()</code> メソッドで JSON の文字列化の挙動をカスタマイズできます。シリアライズされるオブジェクトの代わりに、その <code>toJSON()</code> メソッドが呼び出されたときの返値がシリアライズされます。 <code>JSON.stringify()</code> は <code>toJSON</code> に以下のどれか1つの引数をつけて呼び出します。</p>
<ul>
<li>このオブジェクトがプロパティの値であった場合は、プロパティ名</li>
<li>配列内の値で会った場合は、配列のインデックス番号を文字列で</li>
<li><code>JSON.stringify()</code> がこのオブジェクトに対して直接呼び出された場合は、空文字列</li>
</ul>
<p>例</p>
<pre class="brush: js notranslate">var obj = {
data: 'data',
toJSON (key) {
if (key)
return `Now I am a nested object under key '${key}'`;
else
return this;
}
};
JSON.stringify(obj);
// '{"data":"data"}'
JSON.stringify({ obj }); // Shorthand property names (ES2015).
// '{"obj":"Now I am a nested object under key 'obj'"}'
JSON.stringify([ obj ]);
// '["Now I am a nested object under key '0'"]'
</pre>
<h3 id="循環参照をシリアライズした場合の_JSON.stringify_に関する問題">循環参照をシリアライズした場合の JSON.stringify() に関する問題</h3>
<p><a href="https://www.json.org/">JSON 形式</a>はオブジェクト参照に対応していないため (<a href="http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03">IETF 草稿</a>はありますが)、循環参照のあるオブジェクトをエンコードしようとすると {{JSxRef("TypeError")}} が発生します。</p>
<pre class="brush: js example-bad notranslate">const circularReference = {};
circularReference.myself = circularReference;
// 循環参照をシリアライズすると "TypeError: cyclic object value" が発生
JSON.stringify(circularReference);
</pre>
<p>循環参照をシリアライズするためには、これに対応したライブラリを使用したり (Douglas Crockford による <a href="https://github.com/douglascrockford/JSON-js/blob/master/cycle.js">cycle.js</a> など)、自分自身で解決策を実装したりする方法があります。循環参照を探索してシリアライズされた値に置き換える (または削除する) 必要があるでしょう。</p>
<h3 id="Issue_with_plain_JSON.stringify_for_use_as_JavaScript" name="Issue_with_plain_JSON.stringify_for_use_as_JavaScript">JavaScript としての使用に際してのそのままの JSON.stringify の問題</h3>
<p>従来、 JSON は <a href="http://timelessrepo.com/json-isnt-a-javascript-subset">JavaScript の完全に厳密なサブセットではありません</a>でした。文字コードポイント U+2028 LINE SEPARATOR (改行) と U+2029 PARAGRAPH SEPARATOR (改段落) は JSON テキスト内の文字列リテラルやプロパティ名に使用することができます。しかし、 JavsScript のテキスト内で同様の文脈では使用することができず、 Unicode エスケープを使用した <code>\u2028</code> および <code>\u2029</code> しか使うことができません。これは最近変更され、どちらのコードポイントも JSON と JavaScript の両方の文字列で使用することができるようになりました。</p>
<p>したがって、古い JavaScript エンジンとの互換性が必要な場合は、 <code>JSON.stringify</code> から返された文字列を JavaScript の文字列に代入するために、直接 <code>eval</code> や <code>new Function</code> に渡したり、 <a href="https://ja.wikipedia.org/wiki/JSONP">JSONP</a> URL の一部として用いたりするのは危険です。次のユーティリティを使用することができます。</p>
<pre class="brush: js notranslate">function jsFriendlyJSONStringify (s) {
return JSON.stringify(s).
replace(/\u2028/g, '\\u2028').
replace(/\u2029/g, '\\u2029');
}
var s = {
a: String.fromCharCode(0x2028),
b: String.fromCharCode(0x2029)
};
try {
eval('(' + JSON.stringify(s) + ')');
} catch (e) {
console.log(e); // "SyntaxError: unterminated string literal"
}
// catch する必要はない
eval('(' + jsFriendlyJSONStringify(s) + ')');
// Firefox での console.log はコンソールにログ出力をする場合
// Unicode エスケープを解除するので、alert を使う
alert(jsFriendlyJSONStringify(s)); // {"a":"\u2028","b":"\u2029"}
</pre>
<div class="blockIndicator note">
<p><strong>注</strong>: 配列以外のオブジェクトのプロパティでは、特定の順番で文字列化されることは保証されていません。文字列化された同じオブジェクトの中でプロパティの順番に依存しないようにしてください。</p>
</div>
<pre class="brush: js notranslate">var a = JSON.stringify({ foo: "bar", baz: "quux" })
//'{"foo":"bar","baz":"quux"}'
var b = JSON.stringify({ baz: "quux", foo: "bar" })
//'{"baz":"quux","foo":"bar"}'
console.log(a !== b) // true
// 一部の記憶関数は JSON.stringify を使用して引数をシリアライズしており、
// 上記のような同じオブジェクトに出会った時にキャッチし損ねることがあります
</pre>
<h3 id="Example_of_using_JSON.stringify_with_localStorage" name="Example_of_using_JSON.stringify_with_localStorage">localStorage で JSON.stringify() を使った例</h3>
<p>ユーザーが作成したオブジェクトを格納し、ブラウザーが閉じた後に復元できるようにしたい場合は以下の例が <code>JSON.stringify()</code> を適用した模範例です。</p>
<pre class="brush: js notranslate">// JSON の一例を作成
var session = {
'screens': [],
'state': true
};
session.screens.push({ 'name': 'screenA', 'width': 450, 'height': 250 });
session.screens.push({ 'name': 'screenB', 'width': 650, 'height': 350 });
session.screens.push({ 'name': 'screenC', 'width': 750, 'height': 120 });
session.screens.push({ 'name': 'screenD', 'width': 250, 'height': 60 });
session.screens.push({ 'name': 'screenE', 'width': 390, 'height': 120 });
session.screens.push({ 'name': 'screenF', 'width': 1240, 'height': 650 });
// JSON.stringify() で JSON 文字列に変換してから
// session の名前で localStorage に保存
localStorage.setItem('session', JSON.stringify(session));
// JSON.stringify() で生成されて localStorage に保存された文字列を
// 再び JSON オブジェクトに変換する方法の例
var restoredSession = JSON.parse(localStorage.getItem('session'));
// ここで変数 restoredSession には localStorage に保存されていた
// オブジェクトが入っている
console.log(restoredSession);
</pre>
<h3 id="Well-formed_JSON.stringify" name="Well-formed_JSON.stringify">Well-formed JSON.stringify()</h3>
<p><a href="https://github.com/tc39/proposal-well-formed-stringify">well-formed JSON.stringify 仕様</a>を実装しているエンジンは、サロゲート文字 、 U+D800 から U+DFFF までのすべてのコードポイントを、リテラルではなく Unicode エスケープシーケンスを使用して文字列化します。この変更前は、入力にサロゲート文字が含まれている場合、 <code>JSON.stringify</code> はサロゲート文字をそのまま出力していました。このような文字列は妥当な UTF-8 または UTF-16 でエンコードされていませんでした。</p>
<pre class="brush: js; no-line-numbers notranslate">JSON.stringify("\uD800"); // '"�"'</pre>
<p>しかし、この変更で <code>JSON.stringify</code> は lone surrogates を JSON エスケープシーケンスによって表すようになり、妥当な UTF-8 または UTF-16 でエンコードすることができるようになりました。</p>
<pre class="brush: js; no-line-numbers notranslate">JSON.stringify("\uD800"); // '"\\ud800"'</pre>
<p>この変更では、サロゲート文字の Unicode エスケープをサロゲート文字と同一のものとして扱うため、 <code>JSON.stringify</code> の結果を、 JSON テキストを妥当である限りどのようなものでも受け付ける <code>JSON.parse</code> のような API に渡したときに後方互換性があります。 <code>JSON.stringify</code> の結果を直接解析する場合<em>のみ</em>、 <code>JSON.stringify</code> がこれらのコードポイントに対して2通りのエンコーディングをする可能性があることに注意して扱う必要があります。</p>
<h2 id="Specifications" name="Specifications">仕様書</h2>
<table class="standard-table">
<thead>
<tr>
<th scope="col">仕様書</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{SpecName('ESDraft', '#sec-json.stringify', 'JSON.stringify')}}</td>
</tr>
</tbody>
</table>
<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2>
<div>
<div class="hidden">このページの互換性一覧表は構造化データから生成されています。データに協力していただけるのであれば、 <a class="external" href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> をチェックアウトしてプルリクエストを送信してください。</div>
<p>{{Compat("javascript.builtins.JSON.stringify")}}</p>
</div>
<h2 id="See_also" name="See_also">関連情報</h2>
<ul>
<li>{{JSxRef("JSON.parse()")}}</li>
<li><a href="https://github.com/douglascrockford/JSON-js/blob/master/cycle.js">cycle.js</a> – <code>JSON.decycle</code> と <code>JSON.retrocycle</code> の2つの関数を導入します。これらは循環的な構造と DAG を、拡張されたレトロ互換性のある JSON 形式にエンコードおよびデコードすることができます。</li>
</ul>
|