JSON.parse()不安全,需校验+异常捕获;它只做语法解析,不校验语义或来源,可能因HTML响应、BOM、控制字符等抛错;safeParseJSON应预清洗、捕获SyntaxError、类型断言。

直接用 JSON.parse() 解析字符串是安全的——前提是数据来源可信;一旦涉及用户输入、API 响应或 localStorage 读取,就必须加校验和异常捕获,否则会因格式错误或恶意构造触发 SyntaxError 或静默失败。
为什么不能无条件信任 JSON.parse()
它只做语法解析,不校验语义。比如:"null"、"true"、"123" 都是合法 JSON 字符串,但可能不符合你预期的数据结构;更危险的是,某些服务返回的响应体看似 JSON,实则混入 HTML(如 500 错误页),此时 JSON.parse() 会直接抛错中断流程。
- 常见错误现象:
Uncaught SyntaxError: Unexpected token (说明服务器返回了 HTML) - 典型场景:fetch 后未检查
response.ok就调用response.json(),或从localStorage.getItem('config')读取后直 parse - 关键点:
JSON.parse()不处理编码问题,UTF-8 BOM、不可见控制字符(如\u2028、\u2029)也可能导致解析失败
安全解析的最小可靠封装
核心是三件事:预清洗、异常捕获、类型断言。不要依赖 try/catch 吞掉所有错误,要区分语法错误和其他异常。
function safeParseJSON(str) {
if (typeof str !== 'string') return null;
// 移除常见 BOM 和首尾空白
const trimmed = str.replace(/^\uFEFF/, '').trim();
if (!trimmed) return null;
try {
const parsed = JSON.parse(trimmed);
// 可选:进一步校验是否为 object/array(排除 "hello"、42 等标量)
return (parsed && typeof parsed === 'object') ? parsed : null;
} catch (e) {
if (e instanceof SyntaxError) return null;
throw e; // 其他异常(如内存溢出)不应静默
}
}
- 该函数返回
null表示解析失败,而非抛错,便于业务层统一处理 - 不自动 fallback 到空对象,避免掩盖数据缺失问题
- 不递归清理嵌套字符串中的非法字符(那是数据生产方的责任)
和 response.json() 的区别与协作
浏览器原生 response.json() 内部也调用 JSON.parse(),但它还会检查 Content-Type 并在非 application/json 时抛 TypeError。但它**不检查 HTTP 状态码**,404/500 响应仍会进入 .then() 分支并尝试解析。
立即学习“Java免费学习笔记(深入)”;
- 正确用法:先判断
response.ok,再调用response.json() - 更稳做法:用
safeParseJSON(await response.text())替代response.json(),可绕过 Content-Type 限制,也避免因服务端 header 错误导致的失败 - 注意:
response.text()返回 Promise,需 await;而safeParseJSON是同步函数
真正容易被忽略的不是怎么写 parse 函数,而是忘记检查上游数据是否本就「不该是 JSON」——比如后端文档写的是 JSON,但灰度环境实际返回 plain text;或者 localStorage 里存的是旧版字段,新代码按新 schema 解析时字段缺失却不报错。安全处理的本质,是明确每处 JSON 的契约边界,而不是堆砌防御性代码。











