You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

fetch()加载含单引号的JSON报错,React setState失效求解决方案

解决fetch加载非标准JSON时的SyntaxError问题

你的问题根源在于后端返回的不是标准JSON格式,而是JS对象字面量,再加上你处理单引号的方式错误,导致JSON解析失败。咱们一步步来解决:

问题分析

  1. 你提供的"JSON"其实是JS对象语法:标准JSON要求所有键名必须用双引号包裹(比如"id": {...}而不是id: {...}),但你的返回内容里键都没有双引号。
  2. 你现在用text.replace(/\'/g, '"')把字符串里的单引号(比如Istanbul's里的')替换成双引号,这会破坏字符串结构,变成"Istanbul"s",完全不符合JSON语法,自然会报错。
  3. 之前用ajax()没问题,是因为jQuery的ajax会自动尝试解析非标准的JS对象字面量,而fetch的JSON.parse()是严格遵循JSON规范的。

解决方案

方案1:修复后端输出(最推荐)

这是根本解决办法,让后端返回标准JSON:

  • 所有键名用双引号包裹
  • 字符串内部的单引号转义为\'(比如Istanbul's变成Istanbul\'s)

修改后,前端代码可以简化,直接用fetch的response.json()解析:

componentDidMount() {
  fetch("/json.bc", { method: "POST", body: "cityid=[##cms.form.cityid##]" })
    .then(response => response.json()) // 直接解析为JSON
    .then(Maindata => {
      this.setState(
        state => ({ ...state, data: Maindata }),
        () => { this.reorganiseLibrary(); }
      );
    })
    .catch(error => console.error(error));
}

方案2:前端兼容非标准格式(后端无法修改时)

如果后端没法改,我们可以把返回的JS对象字面量转换成可解析的格式:

方法A:用new Function安全解析(比eval更安全)

因为返回的是JS对象字面量,我们可以用new Function来执行并返回这个对象:

componentDidMount() {
  fetch("/json.bc", { method: "POST", body: "cityid=[##cms.form.cityid##]" })
    .then(response => response.text())
    .then(text => {
      // 把文本转换成JS对象
      var Maindata = new Function('return ' + text)();
      this.setState(
        state => ({ ...state, data: Maindata }),
        () => { this.reorganiseLibrary(); }
      );
    })
    .catch(error => console.error(error));
}

注意:只有当你完全信任后端返回的内容时才用这个方法,避免注入风险。

方法B:正则修正为标准JSON

用正则给无引号的键加上双引号,同时转义字符串里的单引号:

componentDidMount() {
  fetch("/json.bc", { method: "POST", body: "cityid=[##cms.form.cityid##]" })
    .then(response => response.text())
    .then(text => {
      // 1. 给所有键名加上双引号
      // 2. 转义字符串内部的单引号
      const validJson = text
        .replace(/([a-zA-Z_][a-zA-Z0-9_]*):/g, '"$1":')
        .replace(/'/g, '\\\'');
      var Maindata = JSON.parse(validJson);
      this.setState(
        state => ({ ...state, data: Maindata }),
        () => { this.reorganiseLibrary(); }
      );
    })
    .catch(error => console.error(error));
}

这种方式可能存在边缘情况(比如键名包含特殊字符),但大部分场景下能工作。

额外提示

你当前的代码里还有一个小问题:React元素的class属性应该用className,比如return <div className="nodata">No Result</div>;,避免和JS的class关键字冲突。

内容的提问来源于stack exchange,提问作者bita

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:26:57