fetch()加载含单引号的JSON报错,React setState失效求解决方案
解决fetch加载非标准JSON时的SyntaxError问题
你的问题根源在于后端返回的不是标准JSON格式,而是JS对象字面量,再加上你处理单引号的方式错误,导致JSON解析失败。咱们一步步来解决:
问题分析
- 你提供的"JSON"其实是JS对象语法:标准JSON要求所有键名必须用双引号包裹(比如
"id": {...}而不是id: {...}),但你的返回内容里键都没有双引号。 - 你现在用
text.replace(/\'/g, '"')把字符串里的单引号(比如Istanbul's里的')替换成双引号,这会破坏字符串结构,变成"Istanbul"s",完全不符合JSON语法,自然会报错。 - 之前用
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
相关产品推荐
相关产品推荐

