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

语法

¥Syntax

js
JSON.parse(text)
JSON.parse(text, reviver)

参数

¥Parameters

text

要解析为 JSON 的字符串。有关 JSON 语法的说明,请参阅 JSON 对象。

reviver Optional

如果是函数,则规定了解析最初生成的每个值在返回之前如何进行转换。不可调用的值将被忽略。使用以下参数调用该函数:

key

与值关联的键。

value

解析产生的值。

context Optional

保存与当前正在恢复的表达式相关的状态的上下文对象。每次调用 reviver 函数时,它都是一个新对象。它仅在恢复原始值时传递,但当 value 是对象或数组时不传递。它包含以下属性:

source

表示该值的原始 JSON 字符串。

返回值

¥Return value

与给定 JSON text 对应的 ObjectArray、字符串、数字、布尔值或 null 值。

¥The Object, Array, string, number, boolean, or null value corresponding to the given JSON text.

例外情况

¥Exceptions

SyntaxError

如果要解析的字符串不是有效的 JSON,则抛出该异常。

描述

¥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 绑定)和两个参数来调用 reviverkeyvalue,将属性名称表示为字符串(即使是数组)和属性值。对于原始值,会传递一个附加的 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:

js
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:

js
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;
});

示例

¥Examples

使用 JSON.parse()

¥Using JSON.parse()

js
JSON.parse("{}"); // {}
JSON.parse("true"); // true
JSON.parse('"foo"'); // "foo"
JSON.parse('[1, 5, "false"]'); // [1, 5, "false"]
JSON.parse("null"); // null

使用 reviver 参数

¥Using the reviver parameter

js
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:

js
// 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.parse() 不允许尾随逗号

¥JSON.parse() does not allow trailing commas

js
// both will throw a SyntaxError
JSON.parse("[1, 2, 3, 4, ]");
JSON.parse('{"foo" : 1, }');

JSON.parse() 不允许单引号

¥JSON.parse() does not allow single quotes

js
// will throw a SyntaxError
JSON.parse("{'foo': 1}");

规范

Specification
ECMAScript Language Specification
# sec-json.parse

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看