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
|
---
title: JSON.stringify()
slug: Web/JavaScript/Reference/Global_Objects/JSON/stringify
tags:
- JSON
- JSON.stringify()
- JavaScript
- Method
- Reference
- stringify
- 字符串
translation_of: Web/JavaScript/Reference/Global_Objects/JSON/stringify
---
<div>{{JSRef}}</div>
<p><code><strong>JSON.stringify()</strong></code> 方法将一个 JavaScript 对象或值转换为 JSON 字符串,如果指定了一个 replacer 函数,则可以选择性地替换值,或者指定的 replacer 是数组,则可选择性地仅包含数组指定的属性。</p>
<p>{{EmbedInteractiveExample("pages/js/json-stringify.html")}}</p>
<h2 id="Syntax" name="Syntax">语法</h2>
<pre class="syntaxbox"><code>JSON.stringify(<em>value</em>[, <em>replacer</em> [, <em>space</em>]])</code>
</pre>
<h3 id="Parameters" name="Parameters">参数</h3>
<dl>
<dt><code>value</code></dt>
<dd>将要序列化成 一个 JSON 字符串的值。</dd>
<dt><code>replacer</code> {{optional_inline}}</dt>
<dd>如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;如果该参数为 null 或者未提供,则对象所有的属性都会被序列化。</dd>
<dt><code>space</code> {{optional_inline}}</dt>
<dd>指定缩进用的空白字符串,用于美化输出(pretty-print);如果参数是个数字,它代表有多少的空格;上限为10。该值若小于1,则意味着没有空格;如果该参数为字符串(当字符串长度超过10个字母,取其前10个字母),该字符串将被作为空格;如果该参数没有提供(或者为 null),将没有空格。</dd>
<dt>
<h3 id="返回值">返回值</h3>
</dt>
<dd>一个表示给定值的JSON字符串。</dd>
</dl>
<h3 id="异常">异常</h3>
<ul>
<li>当在循环引用时会抛出异常{{JSxRef("TypeError")}} ("cyclic object value")(循环对象值)</li>
<li>当尝试去转换 {{jsxref("BigInt")}} 类型的值会抛出{{JSxRef("TypeError")}} ("BigInt value can't be serialized in JSON")(BigInt值不能JSON序列化).</li>
</ul>
<h2 id="描述">描述</h2>
<p><code>JSON.stringify()</code>将值转换为相应的JSON格式:</p>
<ul>
<li>转换值如果有 toJSON() 方法,该方法定义什么值将被序列化。</li>
<li>非数组对象的属性不能保证以特定的顺序出现在序列化后的字符串中。</li>
<li>布尔值、数字、字符串的包装对象在序列化过程中会自动转换成对应的原始值。</li>
<li><code>undefined</code>、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成 <code>null</code>(出现在数组中时)。函数、undefined 被单独转换时,会返回 undefined,如<code>JSON.stringify(function(){})</code> or <code>JSON.stringify(undefined)</code>.</li>
<li>对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。</li>
<li>所有以 symbol 为属性键的属性都会被完全忽略掉,即便 <code>replacer</code> 参数中强制指定包含了它们。</li>
<li>Date 日期调用了 toJSON() 将其转换为了 string 字符串(同Date.toISOString()),因此会被当做字符串处理。</li>
<li>NaN 和 Infinity 格式的数值及 null 都会被当做 null。</li>
<li>其他类型的对象,包括 Map/Set/WeakMap/WeakSet,仅会序列化可枚举的属性。</li>
</ul>
<h2 id="示例">示例</h2>
<h3 id="使用_JSON.stringify">使用 JSON.stringify</h3>
<pre class="brush: js">JSON.stringify({}); // '{}'
JSON.stringify(true); // 'true'
JSON.stringify("foo"); // '"foo"'
JSON.stringify([1, "false", false]); // '[1,"false",false]'
JSON.stringify({ x: 5 }); // '{"x":5}'
JSON.stringify({x: 5, y: 6});
// "{"x":5,"y":6}"
JSON.stringify([new Number(1), new String("false"), new Boolean(false)]);
// '[1,"false",false]'
JSON.stringify({x: undefined, y: Object, z: Symbol("")});
// '{}'
JSON.stringify([undefined, Object, Symbol("")]);
// '[null,null,null]'
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"}"
</pre>
<h3 id="replacer参数"><code>replacer参数</code></h3>
<p>replacer 参数可以是一个函数或者一个数组。作为函数,它有两个参数,键(key)和值(value),它们都会被序列化。</p>
<p>在开始时, <code><var>replacer</var></code> 函数会被传入一个空字符串作为 <code>key</code> 值,代表着要被 <code>stringify</code> 的这个对象。随后每个对象或数组上的属性会被依次传入。 </p>
<p>函数应当返回JSON字符串中的value, 如下所示:</p>
<ul>
<li>如果返回一个 {{jsxref("Number")}}, 转换成相应的字符串作为属性值被添加入 JSON 字符串。</li>
<li>如果返回一个 {{jsxref("String")}}, 该字符串作为属性值被添加入 JSON 字符串。</li>
<li>如果返回一个 {{jsxref("Boolean")}}, "true" 或者 "false" 作为属性值被添加入 JSON 字符串。</li>
<li>如果返回任何其他对象,该对象递归地序列化成 JSON 字符串,对每个属性调用 replacer 方法。除非该对象是一个函数,这种情况将不会被序列化成 JSON 字符串。</li>
<li>如果返回 undefined,该属性值不会在 JSON 字符串中输出。</li>
</ul>
<p><strong>注意:</strong> 不能用 replacer 方法,从数组中移除值(values),如若返回 undefined 或者一个函数,将会被 null 取代。</p>
<h4 id="例子function">例子(function)</h4>
<pre><code>function replacer(key, value) {
if (typeof value === "string") {
return undefined;
}
return value;
}
var foo = {foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7};
var jsonString = JSON.stringify(foo, replacer);</code></pre>
<p>JSON序列化结果为 <code>{"week":45,"month":7}</code>.</p>
<h4 id="例子array">例子(array)</h4>
<p>如果 <code>replacer</code> 是一个数组,数组的值代表将被序列化成 JSON 字符串的属性名。</p>
<pre><code>JSON.stringify(foo, ['week', 'month']);
// '{"week":45,"month":7}', 只保留 “week” 和 “month” 属性值。</code></pre>
<h3 id="space_参数"><code>space</code> 参数</h3>
<p><code>space </code>参数用来控制结果字符串里面的间距。如果是一个数字, 则在字符串化时每一级别会比上一级别缩进多这个数字值的空格(最多10个空格);如果是一个字符串,则每一级别会比上一级别多缩进该字符串(或该字符串的前10个字符)。</p>
<pre class="brush: js">JSON.stringify({ a: 2 }, null, " "); // '{\n "a": 2\n}'</pre>
<p>使用制表符(\t)来缩进:</p>
<pre class="brush: js">JSON.stringify({ uno: 1, dos : 2 }, null, '\t')
// '{ \
// "uno": 1, \
// "dos": 2 \
// }'
</pre>
<h3 id="toJSON_方法">toJSON 方法</h3>
<p>如果一个被序列化的对象拥有 <code>toJSON</code> 方法,那么该 <code>toJSON</code> 方法就会覆盖该对象默认的序列化行为:不是该对象被序列化,而是调用 <code>toJSON</code> 方法后的返回值会被序列化,例如:</p>
<pre class="brush: js">var obj = {
foo: 'foo',
toJSON: function () {
return 'bar';
}
};
JSON.stringify(obj); // <code>'"bar"'</code>
JSON.stringify({x: obj}); // <code>'{"x":"bar"}'</code>
</pre>
<h3 id="JSON.stringify用作_JavaScript"><code>JSON.stringify</code>用作 JavaScript</h3>
<p>注意 JSON 不是 JavaScript 严格意义上的子集,在 JSON 中不需要省略两条终线(Line separator 和 Paragraph separator),但在 JavaScript 中需要被省略。因此,如果 JSON 被用作 JSONP 时,下面方法可以使用:</p>
<pre><code>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"
}
// No need for a catch
eval('(' + jsFriendlyJSONStringify(s) + ')');
// console.log in Firefox unescapes the Unicode if
// logged to console, so we use alert
alert(jsFriendlyJSONStringify(s)); // {"a":"\u2028","b":"\u2029"}</code></pre>
<h3 id="使用_JSON.stringify_结合_localStorage_的例子">使用 JSON.stringify 结合 localStorage 的例子</h3>
<p>一些时候,你想存储用户创建的一个对象,并且,即使在浏览器被关闭后仍能恢复该对象。下面的例子是 <code>JSON.stringify</code> 适用于这种情形的一个样板:</p>
<pre class="brush: js">// 创建一个示例数据
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 字符串
// 然后使用 localStorage 保存在 session 名称里
localStorage.setItem('session', JSON.stringify(session));
// 然后是如何转换通过 JSON.stringify 生成的字符串,该字符串以 JSON 格式保存在 localStorage 里
var restoredSession = JSON.parse(localStorage.getItem('session'));
// 现在 restoredSession 包含了保存在 localStorage 里的对象
console.log(restoredSession);
</pre>
<h2 id="规范">规范</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">规范名称及链接</th>
<th scope="col">规范状态</th>
</tr>
<tr>
<td>{{SpecName('ES5.1', '#sec-15.12.3', 'JSON.stringify')}}</td>
<td>{{Spec2('ES5.1')}}</td>
</tr>
<tr>
<td>{{SpecName('ES6', '#sec-json.stringify', 'JSON.stringify')}}</td>
<td>{{Spec2('ES6')}}</td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容性">浏览器兼容性</h2>
<p>{{Compat("javascript.builtins.JSON.stringify")}}</p>
<h2 id="相关链接">相关链接</h2>
<ul>
<li>{{JSxRef("JSON.parse()")}}</li>
<li><a href="https://github.com/douglascrockford/JSON-js/blob/master/cycle.js">cycle.js</a> – Introduces two functions: <code>JSON.decycle</code> and <code>JSON.retrocycle</code>. These allow encoding and decoding of cyclical structures and DAGs into an extended and retrocompatible JSON format.</li>
</ul>
|