JSON.parse() 解析不可信字符串有风险,须坚持不解析未校验输入、不执行隐式转换、不依赖 try-catch 掩盖缺陷;仅处理严格 JSON 格式,用 try-catch 区分 SyntaxError 并记录日志;服务端应确保响应为合法 JSON,前端优先用 response.json();解析后需校验字段并防原型污染。

直接用 JSON.parse() 解析不可信字符串存在风险,核心原则是:**不解析未经校验的输入,不执行隐式类型转换,不依赖 try-catch 掩盖逻辑缺陷**。
只解析明确符合 JSON 格式的字符串
JSON 是严格语法格式,不等同于 JavaScript 对象字面量。以下写法合法:
-
'{"name":"Alice","age":30}'(双引号键名、双引号字符串值) '[1, "hello", true, null]'
以下写法 不是 JSON,不能直接传给 JSON.parse():
-
"{name:'Alice'}"(单引号、未引号键名)→ 这是 JS 对象字面量,非 JSON -
"{'name':'Alice'}"(单引号)→ JSON 要求必须用双引号 -
"undefined"或"function(){}"→ JSON 不支持这些值
始终用 try...catch 包裹,并区分错误类型
解析失败时抛出 SyntaxError,但不能假设所有异常都来自语法问题。建议:
立即学习“Java免费学习笔记(深入)”;
- 捕获后检查
error instanceof SyntaxError,避免把其他错误误判为“解析失败” - 不要静默吞掉错误;记录日志或返回明确的失败信号(如
null或undefined) - 避免在 catch 中尝试 fallback 解析(如 eval),这会引入严重安全漏洞
示例:
function safeParse(jsonStr) {
try {
return JSON.parse(jsonStr);
} catch (e) {
if (e instanceof SyntaxError) {
console.warn('Invalid JSON:', jsonStr);
return null;
}
throw e; // 其他异常原样抛出
}
}
服务端返回前应做预处理,客户端不承担校验责任
前端不应替后端兜底。安全做法是:
- 后端确保 API 响应 Content-Type 为
application/json - 后端对输出数据做 JSON 编码(如用
JSON.stringify()或框架内置序列化),不拼接字符串 - 前端收到响应后,先检查
response.headers.get('content-type')?.includes('json'),再调用response.json()(它内部已封装安全解析)
避免手动读取 response.text() 后再 JSON.parse(),除非有特殊需求且已确认内容可信。
警惕原型污染与恶意键名
JSON.parse() 本身不会导致原型污染,但如果解析结果被不安全地合并到对象(如使用 Object.assign({}, parsed) 或第三方 deep-merge 工具),且原始 JSON 包含 "__proto__" 或 "constructor" 等特殊键,则可能触发污染。
- 解析后立即校验关键字段是否存在、类型是否正确(如
typeof data.id === 'string') - 避免将解析结果直接用于对象扩展或构造函数调用
- 必要时用白名单过滤属性:
const safeData = Object.fromEntries(Object.entries(parsed).filter(([k]) => allowedKeys.includes(k)))










