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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 14:42:47