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

Redis缓存用户报Unexpected token o in JSON at position 1错误

报错原因

这个报错的核心触发逻辑是:JSON.parse()接收到的入参不是合法的JSON格式字符串,当传入值是JS对象(含Promise对象、普通Object)时,JS会先隐式调用入参的toString()方法转成字符串,这类对象转字符串的结果固定为"[object Xxx]",字符串索引0位置是[、索引1位置是o,和报错信息里position 1位置出现非法字符o完全吻合。

对应到你的代码,有3个明确问题:

  • 调用client.get()读取Redis缓存时没有加await关键字。Node.js生态的Redis客户端所有IO操作都是异步的,不加await拿到的不是缓存的字符串值,而是一个未完成的Promise对象,把这个对象传入JSON.parse()就会触发你看到的报错。
  • 缓存写入逻辑后多了一行无意义的throw error;,这里的error变量从未被定义,代码走到这行必然抛出未定义变量错误,且该行后面的console.log(error)永远不会执行。
  • 缓存key硬编码为name,和请求的用户id完全无关,会导致所有用户查询请求都读写同一个缓存值,出现数据串号问题。
  • 数据库查询到用户数据后没有正常返回响应,逻辑被无效的throw打断,前端拿不到正确的查询结果。
修复方案

按以下步骤修改代码即可:

  1. 给client.get()、client.set()调用都加上await关键字,确保拿到实际的Redis操作返回值
  2. 删除多余的throw error;无效代码
  3. 将缓存key改为和用户id绑定的格式(如user:${id}),避免不同用户缓存互相覆盖
  4. 补上数据库查询成功后的响应返回逻辑,修正缓存成功提示的拼写错误

修复后的完整代码如下:

exports.getOne = async (req, res) => {
  let id = req.params.id;
  try {
    // 加await读取缓存,key绑定用户id做隔离
    const cachedUser = await client.get(`user:${id}`);
    if(cachedUser){
      const userData = JSON.parse(cachedUser);
      console.log(userData);
      return res.status(200).send(userData);
    }
    let user = await User.findById(id);
    if(!user) {
      return res.status(400).json('This user does not exist');
    }
    // 加await写入缓存
    await client.set(`user:${id}`, JSON.stringify(user));
    console.log('Successfully cached')
    // 正常返回查询到的用户数据
    return res.status(200).send(user);
  } catch (error) {
    console.log(error);
    return res.status(500).json(error.message)
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 01:42:17