前言

这是在写多人博客管理系统练习项目时遇到的一个坑(巨坑)。因为学习视频中老师没有提到,所以得自己解决。但是又因为个人的错误又有一定的特性,导致某些方面没有想到而花费了大量的时间。在此记录一下,防止以后再犯同样的错误,也方便别人能解决错误。如果你百度查到 SyntaxError: Unexpected token R in JSON at position 0 报错并按照里面的方法还是无法解决不妨将这篇笔记看完。

报错信息1

在这里插入图片描述

报错代码

// 联合查询两个集合信息(文章和用户,但是这里只展示了部分字段)
let articles = await Article.find({}, { cover: 1, _id: 1, title: 1, publishDate: 1 }).populate('author', { userName: 1, _id: 0 });
// res.send(articles);
// 渲染页面
res.render('admin/article', {
    articles: articles,
    count: count
});

报错原因

根据报错信息可以知道是在字符串数据格式向 json 数据格式转换时发生了错误。那为什么会这样呢?从数据获取得到的不是一个个对象组成的数据集合吗?在用户管理页面(前面实现的一个功能没有报错)输出单纯查询到的用户信息的格式如下(注意:没有涉及联合查询,只截取部分):

在这里插入图片描述

文章管理页面使用集合关联查询得到的数据中结构唯一不同的内容如下图,那问题是不是就应该出现在下面标记的那部分呢?

在这里插入图片描述

参考他人的笔记,原因是 mongoose 返回的 author 对象不是普通对象,而是所谓的 mongoose 文档对象。里面的属性存在与普通对象不一样的格式,所以在解析时出现错误

解决方法

方法一:结合原因我们需要将 author 属性转换为普通对象,有一种方式是在查询数据时链式调用 lean() 方法这会使 mongoose 返回普通对象而不再是 mongoose 文档对象

方法二:可以先使用 JSON.string() 方法将返回的集合整体转换为 json 字符串后再使用 JSON.parse() 方法将其解析为 json 对象。代码示例如下:

    let articles = await Article.find({}, { cover: 1, _id: 1, title: 1, publishDate: 1 }).populate('author', { userName: 1, _id: 0 });
    let articles1 = JSON.stringify(articles);
    let articles2 = JSON.parse(articles1);
    // console.log(articles == articles2); // false
    // res.send(articles);
    res.render('admin/article', {
        articles: articles2,
        count: count
    });

将 articles 转换为字符串后再次将其转换为 json 对象即可解决问题,如果输出 articles 和 articles2 看不出两者有什么不同(为了方便对比特意关闭了浏览器插件)。如图两者一样的输出,但是如果使用 == 比较两者返回的是 false

在这里插入图片描述

你还没有解决吗?

如果你还没有解决那可能是跟我一样问题了。我是在测试用户的删除功能时将添加该文章的用户删除了,而其相应的文章也该从数据库中删除。但是我没有将相应的文章删除,这会导致在查询文章信息时用户 author 字段是 null 值。这样即使使用上述方法也会出现另一个错误 SyntaxError: Unexpected token T in JSON at position 0
在这里插入图片描述

在这里插入图片描述

其实是一样的原理,因为在解析本该遇到普通对象的值时遇到的却是 null 。但又不是跟前面那样是文档对象,所以格式上不同错误信息提示解析遇到的不合法内容也就不同。

当然还有一种可能就是你渲染的模板出现了问题,例如在模板中导入骨架模板文件时写错单词(我就有一次将 extend 写成 extends),或者其他模板填充标签出错等。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐