如何用javascript解析json_安全处理json数据要注意什么【教程】

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() 分支并尝试解析。

  • 正确用法:先判断 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 的契约边界,而不是堆砌防御性代码。