JSON.parse()
JSON.parse()
静态方法解析 JSON 字符串,构造该字符串描述的 JavaScript 值或对象。可以提供一个可选的 reviver 函数,以便在返回结果对象之前对其执行转换。
¥The JSON.parse()
static method parses a JSON string, constructing the JavaScript value or object described by the string. An optional reviver function can be provided to perform a transformation on the resulting object before it is returned.
Try it
语法
参数
返回值
例外情况
描述
¥Description
JSON.parse()
根据 JSON 语法 解析 JSON 字符串,然后计算该字符串,就像它是 JavaScript 表达式一样。一段 JSON 文本表示与同一 JavaScript 表达式不同的值的唯一实例是在处理 "__proto__"
键时 — 请参阅 对象字面量语法与 JSON。
¥JSON.parse()
parses a JSON string according to the JSON grammar, then evaluates the string as if it's a JavaScript expression. The only instance where a piece of JSON text represents a different value from the same JavaScript expression is when dealing with the "__proto__"
key — see Object literal syntax vs. JSON.
恢复参数
¥The reviver parameter
如果指定了 reviver
,则解析计算出的值会在返回之前进行转换。具体来说,计算值及其所有属性(以 depth-first 方式,从最嵌套的属性开始,继续到原始值本身)单独运行通过 reviver
。
¥If a reviver
is specified, the value computed by parsing is transformed before being returned. Specifically, the computed value and all its properties (in a depth-first fashion, beginning with the most nested properties and proceeding to the original value itself) are individually run through the reviver
.
使用包含正在处理为 this
的属性的对象(除非将 reviver
定义为箭头函数,在这种情况下没有单独的 this
绑定)和两个参数来调用 reviver
:key
和 value
,将属性名称表示为字符串(即使是数组)和属性值。对于原始值,会传递一个附加的 context
参数,其中包含该值的源文本。如果 reviver
函数返回 undefined
(或不返回任何值 — 例如,如果执行到函数末尾),则该属性将从对象中删除。否则,该属性将被重新定义为返回值。如果 reviver
只转换某些值而不转换其他值,请务必按原样返回所有未转换的值 - 否则,它们将从结果对象中删除。
¥The reviver
is called with the object containing the property being processed as this
(unless you define the reviver
as an arrow function, in which case there's no separate this
binding) and two arguments: key
and value
, representing the property name as a string (even for arrays) and the property value. For primitive values, an additional context
parameter is passed, which contains the source text of this value. If the reviver
function returns undefined
(or returns no value — for example, if execution falls off the end of the function), the property is deleted from the object. Otherwise, the property is redefined to be the return value. If the reviver
only transforms some values and not others, be certain to return all untransformed values as-is — otherwise, they will be deleted from the resulting object.
与 JSON.stringify()
的 replacer
参数类似,对于数组和对象,最后将在根值上调用 reviver
,其中 key
为空字符串,value
为根对象。对于其他有效的 JSON 值,reviver
的工作方式类似,并且使用空字符串作为 key
和值本身作为 value
调用一次。
¥Similar to the replacer
parameter of JSON.stringify()
, for arrays and objects, reviver
will be last called on the root value with an empty string as the key
and the root object as the value
. For other valid JSON values, reviver
works similarly and is called once with an empty string as the key
and the value itself as the value
.
如果从 reviver
返回另一个值,该值将完全替换最初解析的值。这甚至适用于根值。例如:
¥If you return another value from reviver
, that value will completely replace the originally parsed value. This even applies to the root value. For example:
const transformedObj1 = JSON.parse('[1,5,{"s":1}]', (key, value) => {
return typeof value === "object" ? undefined : value;
});
console.log(transformedObj1); // undefined
一般来说,没有办法解决这个问题。你不能专门处理 key
为空字符串的情况,因为 JSON 对象也可以包含为空字符串的键。在实现恢复器时,你需要非常准确地知道每个键需要什么样的转换。
¥There is no way to work around this generically. You cannot specially handle the case where key
is an empty string, because JSON objects can also contain keys that are empty strings. You need to know very precisely what kind of transformation is needed for each key when implementing the reviver.
请注意,reviver
在解析值后运行。因此,例如,JSON 文本中的数字将已经转换为 JavaScript 数字,并且可能会在此过程中丢失精度。在不损失精度的情况下传输大量数字的一种方法是将它们序列化为字符串,并将它们恢复为 BigInts 或其他适当的任意精度格式。
¥Note that reviver
is run after the value is parsed. So, for example, numbers in JSON text will have already been converted to JavaScript numbers, and may lose precision in the process. One way to transfer large numbers without loss of precision is to serialize them as strings, and revive them to BigInts, or other appropriate arbitrary precision formats.
你还可以使用 context.source
属性来访问表示该值的原始 JSON 源文本,如下所示:
¥You can also use the context.source
property to access the original JSON source text representing the value, as shown below:
const bigJSON = '{"gross_gdp": 12345678901234567890}';
const bigObj = JSON.parse(bigJSON, (key, value, context) => {
if (key === "gross_gdp") {
// Ignore the value because it has already lost precision
return BigInt(context.source);
}
return value;
});
示例
使用 JSON.parse()
使用 reviver 参数
¥Using the reviver parameter
JSON.parse(
'{"p": 5}',
(key, value) =>
typeof value === "number"
? value * 2 // return value * 2 for numbers
: value, // return everything else unchanged
);
// { p: 10 }
JSON.parse('{"1": 1, "2": 2, "3": {"4": 4, "5": {"6": 6}}}', (key, value) => {
console.log(key);
return value;
});
// 1
// 2
// 4
// 6
// 5
// 3
// ""
与 JSON.stringify() 的替换器配对时使用 reviver
¥Using reviver when paired with the replacer of JSON.stringify()
为了使值正确往返(即,它被反序列化为相同的原始对象),序列化过程必须保留类型信息。例如,你可以使用 JSON.stringify()
的 replacer
参数来实现此目的:
¥In order for a value to properly round-trip (that is, it gets deserialized to the same original object), the serialization process must preserve the type information. For example, you can use the replacer
parameter of JSON.stringify()
for this purpose:
// Maps are normally serialized as objects with no properties.
// We can use the replacer to specify the entries to be serialized.
const map = new Map([
[1, "one"],
[2, "two"],
[3, "three"],
]);
const jsonText = JSON.stringify(map, (key, value) =>
value instanceof Map ? Array.from(value.entries()) : value,
);
console.log(jsonText);
// [[1,"one"],[2,"two"],[3,"three"]]
const map2 = JSON.parse(jsonText, (key, value) =>
Array.isArray(value) ? new Map(value) : value,
);
console.log(map2);
// Map { 1 => "one", 2 => "two", 3 => "three" }
由于 JSON 没有用于注释类型元数据的语法空间,因此为了恢复不是普通对象的值,你必须考虑以下情况之一:
¥Because JSON has no syntax space for annotating type metadata, in order to revive values that are not plain objects, you have to consider one of the following:
- 将整个对象序列化为字符串并为其添加类型标记作为前缀。
- "猜测" 基于数据的结构(例如,二元数组的数组)
- 如果有效负载的形状是固定的,则基于属性名称(例如,所有名为
registry
的属性都包含Map
对象)。
非法 JSON
¥Illegal JSON
当 JSON.parse
收到不符合 JSON 语法的字符串时,它会抛出 SyntaxError
。
¥When JSON.parse
receives a string that does not conform to the JSON grammar, it throws a SyntaxError
.
JSON 中的数组和对象不能有 尾随逗号:
¥Arrays and objects cannot have trailing commas in JSON:
JSON.parse("[1, 2, 3, 4, ]");
// SyntaxError: Unexpected token ] in JSON at position 13
JSON.parse('{"foo": 1, }');
// SyntaxError: Unexpected token } in JSON at position 12
JSON 字符串必须用双引号(而不是单引号)分隔:
¥JSON strings must be delimited by double (not single) quotes:
JSON.parse("{'foo': 1}");
// SyntaxError: Unexpected token ' in JSON at position 1
JSON.parse("'string'");
// SyntaxError: Unexpected token ' in JSON at position 0
如果你在 JavaScript 字符串文字中编写 JSON,则应使用单引号来分隔 JavaScript 字符串文字,或者转义分隔 JSON 字符串的双引号:
¥If you are writing JSON inside a JavaScript string literal, you should either use single quotes to delimit the JavaScript string literal, or escape the double quotes that delimit the JSON string:
JSON.parse('{"foo": 1}'); // OK
JSON.parse("{\"foo\": 1}"); // OK
规范
Specification |
---|
ECMAScript Language Specification # sec-json.parse |
浏览器兼容性
BCD tables only load in the browser