aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/javascript/reference/global_objects/json/parse/index.html
blob: e1e970a1e4418f027fd091b81a7f5b3cf5cfac4f (plain)
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
---
title: JSON.parse()
slug: Web/JavaScript/Reference/Global_Objects/JSON/parse
tags:
  - ECMAScript 5
  - JSON
  - JavaScript
  - 参考
  - 方法
translation_of: Web/JavaScript/Reference/Global_Objects/JSON/parse
---
<div>{{JSRef}}</div>

<p><code><strong>JSON.parse()</strong></code> 方法用来解析JSON字符串,构造由字符串描述的JavaScript值或对象。提供可选的 <strong>reviver</strong> 函数用以在返回之前对所得到的对象执行变换(操作)。</p>

<div>{{EmbedInteractiveExample("pages/js/json-parse.html")}}</div>



<h2 id="语法">语法</h2>

<pre class="syntaxbox">JSON.parse(<var>text</var>[, <var>reviver</var>])</pre>

<h3 id="参数">参数</h3>

<dl>
 <dt><code>text</code></dt>
 <dd>要被解析成 JavaScript 值的字符串,关于JSON的语法格式,请参考:{{jsxref("JSON")}}</dd>
 <dt><code>reviver</code> {{optional_inline()}}</dt>
 <dd>转换器, 如果传入该参数(函数),可以用来修改解析生成的原始值,调用时机在 parse 函数返回之前。</dd>
</dl>

<h3 id="返回值">返回值</h3>

<p>{{jsxref("Object")}} 类型, 对应给定 JSON 文本的对象/值。</p>

<h3 id="异常">异常</h3>

<p>若传入的字符串不符合 JSON 规范,则会抛出 {{jsxref("SyntaxError")}} 异常。</p>

<h2 id="示例">示例</h2>

<h3 id="使用_JSON.parse">使用 <code>JSON.parse()</code></h3>

<pre class="brush: js">JSON.parse('{}');              // {}
JSON.parse('true');            // true
JSON.parse('"foo"');           // "foo"
JSON.parse('[1, 5, "false"]'); // [1, 5, "false"]
JSON.parse('null');            // null
</pre>

<h3 id="使用_reviver_函数">使用 <code>reviver</code> 函数</h3>

<p>如果指定了 <code>reviver</code> 函数,则解析出的 JavaScript 值(解析值)会经过一次转换后才将被最终返回(返回值)。更具体点讲就是:解析值本身以及它所包含的所有属性,会按照一定的顺序(从最最里层的属性开始,一级级往外,最终到达顶层,也就是解析值本身)分别的去调用 <code>reviver</code> 函数,在调用过程中,当前属性所属的对象会作为 <code>this</code> 值,当前属性名和属性值会分别作为第一个和第二个参数传入 <code>reviver</code> 中。如果 <code>reviver</code> 返回 <code>undefined</code>,则当前属性会从所属对象中删除,如果返回了其他值,则返回的值会成为当前属性新的属性值。</p>

<p>当遍历到最顶层的值(解析值)时,传入 <code>reviver</code> 函数的参数会是空字符串 <code>""</code>(因为此时已经没有真正的属性)和当前的解析值(有可能已经被修改过了),当前的 <code>this</code> 值会是 <code>{"": 修改过的解析值}</code>,在编写 <code>reviver</code> 函数时,要注意到这个特例。(这个函数的遍历顺序依照:从最内层开始,按照层级顺序,依次向外遍历)</p>

<pre class="brush: js">JSON.parse('{"p": 5}', function (k, v) {
    if(k === '') return v;     // 如果到了最顶层,则直接返回属性值,
    return v * 2;              // 否则将属性值变为原来的 2 倍。
});                            // { p: 10 }

JSON.parse('{"1": 1, "2": 2,"3": {"4": 4, "5": {"6": 6}}}', function (k, v) {
    console.log(k); // 输出当前的属性名,从而得知遍历顺序是从内向外的,
                    // 最后一个属性名会是个空字符串。
    return v;       // 返回原始属性值,相当于没有传递 reviver 参数。
});

// 1
// 2
// 4
// 6
// 5
// 3
// ""
</pre>

<h3 id="JSON.parse_不允许用逗号作为结尾"><code>JSON.parse()</code> 不允许用逗号作为结尾</h3>

<pre class="example-bad brush: js">// both will throw a SyntaxError
JSON.parse("[1, 2, 3, 4, ]");
JSON.parse('{"foo" : 1, }');
</pre>

<h2 id="Polyfill">Polyfill</h2>

<pre class="brush: js">// From https://github.com/douglascrockford/JSON-js/blob/master/json2.js
if (typeof JSON.parse !== "function") {
    var rx_one = /^[\],:{}\s]*$/;
    var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
    var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
    var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
    var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
    JSON.parse = function(text, reviver) {

        // The parse method takes a text and an optional reviver function, and returns
        // a JavaScript value if the text is a valid JSON text.

        var j;

        function walk(holder, key) {

            // The walk method is used to recursively walk the resulting structure so
            // that modifications can be made.

            var k;
            var v;
            var value = holder[key];
            if (value &amp;&amp; typeof value === "object") {
                for (k in value) {
                    if (Object.prototype.hasOwnProperty.call(value, k)) {
                        v = walk(value, k);
                        if (v !== undefined) {
                            value[k] = v;
                        } else {
                            delete value[k];
                        }
                    }
                }
            }
            return reviver.call(holder, key, value);
        }


        // Parsing happens in four stages. In the first stage, we replace certain
        // Unicode characters with escape sequences. JavaScript handles many characters
        // incorrectly, either silently deleting them, or treating them as line endings.

        text = String(text);
        rx_dangerous.lastIndex = 0;
        if (rx_dangerous.test(text)) {
            text = text.replace(rx_dangerous, function(a) {
                return (
                    "\\u" +
                    ("0000" + a.charCodeAt(0).toString(16)).slice(-4)
                );
            });
        }

        // In the second stage, we run the text against regular expressions that look
        // for non-JSON patterns. We are especially concerned with "()" and "new"
        // because they can cause invocation, and "=" because it can cause mutation.
        // But just to be safe, we want to reject all unexpected forms.

        // We split the second stage into 4 regexp operations in order to work around
        // crippling inefficiencies in IE's and Safari's regexp engines. First we
        // replace the JSON backslash pairs with "@" (a non-JSON character). Second, we
        // replace all simple value tokens with "]" characters. Third, we delete all
        // open brackets that follow a colon or comma or that begin the text. Finally,
        // we look to see that the remaining characters are only whitespace or "]" or
        // "," or ":" or "{" or "}". If that is so, then the text is safe for eval.

        if (
            rx_one.test(
                text
                .replace(rx_two, "@")
                .replace(rx_three, "]")
                .replace(rx_four, "")
            )
        ) {

            // In the third stage we use the eval function to compile the text into a
            // JavaScript structure. The "{" operator is subject to a syntactic ambiguity
            // in JavaScript: it can begin a block or an object literal. We wrap the text
            // in parens to eliminate the ambiguity.

            j = eval("(" + text + ")");

            // In the optional fourth stage, we recursively walk the new structure, passing
            // each name/value pair to a reviver function for possible transformation.

            return (typeof reviver === "function") ?
                walk({
                    "": j
                }, "") :
                j;
        }

        // If the text is not JSON parseable, then a SyntaxError is thrown.

        throw new SyntaxError("JSON.parse");
    };
}</pre>

<h2 id="规范">规范</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">规范名称</th>
   <th scope="col">规范状态</th>
   <th scope="col">备注</th>
  </tr>
  <tr>
   <td>{{SpecName('ES5.1', '#sec-15.12.2', 'JSON.parse')}}</td>
   <td>{{Spec2('ES5.1')}}</td>
   <td>首次定义,于 JavaScript 1.7 版本中实现。</td>
  </tr>
  <tr>
   <td>{{SpecName('ES6', '#sec-json.parse', 'JSON.parse')}}</td>
   <td>{{Spec2('ES6')}}</td>
   <td></td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-json.parse', 'JSON.parse')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td></td>
  </tr>
 </tbody>
</table>

<h2 id="浏览器兼容性">浏览器兼容性</h2>

<div>


<p>{{Compat("javascript.builtins.JSON.parse")}}</p>
</div>

<h2 id="相关链接">相关链接</h2>

<ul>
 <li>{{jsxref("JSON.stringify()")}}</li>
</ul>