Object.keys异常:React中JSON解析结果被当作字符串处理
问题:React中解析JSON字符串后无法正确获取对象键值
控制台测试正常结果
逐行执行以下代码时,能得到预期结果,正常获取对象的键:
content = "{ \"hello\":\"world\" }" // 输出: '{ "hello":"world" }' JSON.parse(content) // 输出: {hello: 'world'} Object.keys(JSON.parse(content)) // 输出: ['hello']
React应用中的异常表现
在React中使用axios请求Rails后端接口时,代码如下:
React.useEffect(() => { axios.get(`${API_ENDPOINT}/appointments/24/goal_notes/1.json`).then((response) => { const content = response?.data?.content console.log(content); console.log(JSON.parse(content)); console.log(Object.keys(JSON.parse(content))); // setAppointmentNoteContent(response?.data?.content); }); }, []);
实际控制台输出却异常:
"{ \"hello\":\"world\" }" { "hello":"world" } ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18']
第三个日志把解析后的对象当成字符串处理,返回的是字符串的索引键,而非目标对象的实际键。怀疑问题源于Rails后端的json列。
解决办法
问题核心是Rails后端返回的content被双重序列化了:Rails的json类型列存入时会自动序列化一次,后端返回时如果再次做JSON序列化,就会导致前端拿到的是转义后的JSON字符串(看起来像对象,但本质还是字符串)。
前端层面解决
做双重JSON解析即可拿到真正的对象:
React.useEffect(() => { axios.get(`${API_ENDPOINT}/appointments/24/goal_notes/1.json`).then((response) => { const content = response?.data?.content // 先解析一次得到内层字符串,再解析一次得到目标对象 const parsedContent = JSON.parse(JSON.parse(content)); console.log(Object.keys(parsedContent)); // 此时输出 ['hello'] // setAppointmentNoteContent(parsedContent); }); }, []);
也可以写个通用解析函数,兼容不同情况:
const safeParseContent = (str) => { try { let result = JSON.parse(str); // 如果解析后仍是字符串,说明需要二次解析 if (typeof result === 'string') { result = JSON.parse(result); } return result; } catch (error) { console.error('JSON解析失败:', error); return {}; } }; // 在useEffect中调用 const parsedContent = safeParseContent(content); console.log(Object.keys(parsedContent));
后端层面解决
从根源避免双重序列化,在Rails控制器中返回content时,先反序列化原始的json列内容:
# Rails控制器示例代码 def show goal_note = GoalNote.find(params[:id]) # 将json列的内容反序列化后再返回 render json: { # 其他字段... content: JSON.parse(goal_note.content) } end
这样前端收到的content就是直接可用的对象,甚至axios会自动解析响应,无需手动调用JSON.parse。
内容的提问来源于stack exchange,提问作者Jeff Zivkovic
相关产品推荐
相关产品推荐

