JSON.parse()
JSON.parse()
静态方法分析 JSON 字符串,构造由字符串描述的 JavaScript 值或对象。可以提供可选的 reviver 函数,在返回结果对象之前对其执行转换。
试一试
语法
JSON.parse(text)
JSON.parse(text, reviver)
参数
返回值
异常
SyntaxError
-
如果要分析的字符串不是有效的 JSON,则抛出此异常。
描述
JSON.parse()
根据 JSON 语法 分析 JSON 字符串,然后将其评估为 JavaScript 表达式。JSON 文本表示与相同 JavaScript 表达式不同的值的唯一情况是处理 "__proto__"
键时 - 请参阅 对象字面量语法与 JSON。
reviver 参数
如果指定了 reviver
,则在返回之前会转换通过分析计算的值。具体来说,计算出的值及其所有属性(以深度优先方式,从最嵌套的属性开始,一直到原始值本身)都会单独通过 reviver
运行。
reviver
使用包含正在处理的属性的对象作为 this
(除非您将 reviver
定义为箭头函数,在这种情况下没有单独的 this
绑定)以及两个参数调用:key
和 value
,分别表示属性名称(即使对于数组)和属性值。对于基本值,会传递额外的 context
参数,其中包含此值的源文本。如果 reviver
函数返回 undefined
(或不返回值 - 例如,如果执行从函数末尾退出),则该属性将从对象中删除。否则,该属性将重新定义为返回值。如果 reviver
仅转换某些值而不是其他值,请务必按原样返回所有未转换的值 - 否则,它们将从结果对象中删除。
类似于 JSON.stringify()
的 replacer
参数,对于数组和对象,reviver
将最后使用空字符串作为 key
和根对象作为 value
调用根值。对于其他有效 JSON 值,reviver
的工作方式类似,并且使用空字符串作为 key
和值本身作为 value
调用一次。
如果您从 reviver
返回另一个值,则该值将完全替换最初分析的值。这甚至适用于根值。例如
const transformedObj1 = JSON.parse('[1,5,{"s":1}]', (key, value) => {
return typeof value === "object" ? undefined : value;
});
console.log(transformedObj1); // undefined
无法普遍解决此问题。您无法专门处理 key
为空字符串的情况,因为 JSON 对象也可以包含键为空字符串的键。在实现 reviver 时,您需要非常精确地知道每个键需要哪种转换。
请注意,reviver
在分析值后运行。因此,例如,JSON 文本中的数字将已转换为 JavaScript 数字,并且在此过程中可能会丢失精度。在不丢失精度的情况下传输大数字的一种方法是将其序列化为字符串,并将其恢复为 BigInts 或其他合适的任意精度格式。
您还可以使用 context.source
属性访问表示该值的原始 JSON 源文本,如下所示
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()
JSON.parse("{}"); // {}
JSON.parse("true"); // true
JSON.parse('"foo"'); // "foo"
JSON.parse('[1, 5, "false"]'); // [1, 5, "false"]
JSON.parse("null"); // null
使用 reviver 参数
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
// ""
将 reviver 与 JSON.stringify() 的 replacer 配合使用
为了使值能够正确往返(即,它被反序列化为相同的原始对象),序列化过程必须保留类型信息。例如,您可以为此目的使用 JSON.stringify()
的 replacer
参数
// 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 没有用于注释类型元数据的语法空间,因此为了恢复不是普通对象的值,您必须考虑以下之一
- 将整个对象序列化为字符串,并在其前面加上类型标签。
- 根据数据的结构“猜测”(例如,由两个成员数组组成的数组)
- 如果有效负载的形状是固定的,则基于属性名称(例如,所有名为
registry
的属性都保存Map
对象)。
非法的 JSON
当 JSON.parse
收到不符合 JSON 语法的字符串时,它会抛出 SyntaxError
。
数组和对象在 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.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 字符串的双引号
JSON.parse('{"foo": 1}'); // OK
JSON.parse("{\"foo\": 1}"); // OK
规范
规范 |
---|
ECMAScript 语言规范 # sec-json.parse |
浏览器兼容性
BCD 表格仅在启用 JavaScript 的浏览器中加载。