读取本地JSON文件并通过POST请求发送时出现JSON解析错误或请求体为空的问题求助
读取本地JSON文件并通过POST请求发送时出现JSON解析错误或请求体为空的问题求助
我最近碰到了一个挺棘手的问题:页面上有个文件输入框,选好JSON文件后用FileReader读取内容,想通过POST请求把内容传到后端,但试了各种请求头配置、解析/字符串化的组合,要么后端拿到的req.body是空的,要么就抛出SyntaxError: Unexpected token o in JSON at position 1的错误。翻了好多相关帖子还是没搞懂哪里错了,下面是我的代码:
前端代码
// 选择JSON文件后点击上传按钮时调用的函数,用于读取文件内容 const upload = async () => { var fileReader = new FileReader(); const data = fileReader.onload = function(e){ let data = JSON.parse(e.target.result); const URL = '/upload'; fetch(URL, { method: 'POST', headers: {'Content-Type' : 'application/json'}, body: {data} }).then((response) => { if(!response.ok){ throw new Error('Something went wrong') } }) .catch((e) => { console.log(e) }); } fileReader.readAsText(document.querySelector("#input").files[0], 'UTF-8'); }
后端代码
app.use(express.json()); // 清空数据库并从JSON文件重新上传新问题 app.post('/upload', async (req, res) => { // 创建客户端对象并等待连接 const client = new MongoClient(URL); await client.connect(); // 设置数据库 const db = client.db('trivia'); // 删除数据库中所有数据 db.collection('questions').deleteMany(); // 用新问题重新填充数据库 console.log(req.body); })
我试过解析后直接发、字符串化后发,甚至两种都做,但就是搞不清到底该用什么格式发送。现在根据报错信息,看起来数据是作为JSON对象发送的?我的数据格式是一个包含多个JSON对象的数组:[{}, {}, {}]。
问题分析&解决方案
其实你遇到的问题核心很明确:
Unexpected token o错误原因:你把已经解析成JavaScript对象的data直接放到了body里,但fetch不会自动把JS对象转成JSON字符串——它会把对象转成[object Object]这种无效的JSON格式,后端用express.json()解析时自然会报错。- 空请求体问题:大多是因为请求头
Content-Type和实际发送的内容格式不匹配,或者发送的不是合法的JSON字符串。
修正后的前端代码
const upload = () => { const fileReader = new FileReader(); fileReader.onload = function(e){ // 先解析文件内容为JS对象(确保文件是合法JSON) const jsonData = JSON.parse(e.target.result); const URL = '/upload'; fetch(URL, { method: 'POST', headers: { 'Content-Type' : 'application/json' }, // 关键:把JS对象转成JSON字符串作为请求体 body: JSON.stringify(jsonData) // 如果后端期望接收带data字段的结构,就改成:JSON.stringify({ data: jsonData }) }) .then(async (response) => { if(!response.ok){ throw new Error('Something went wrong') } // 可选:处理后端返回的响应 const result = await response.json(); console.log('上传成功', result); }) .catch((e) => { console.error('上传失败:', e); }); } // 增加文件选择判断,避免无文件时触发上传 const selectedFile = document.querySelector("#input").files[0]; if (selectedFile) { fileReader.readAsText(selectedFile, 'UTF-8'); } else { console.log('请先选择一个JSON文件'); } }
配套优化后的后端代码
如果前端发送的是纯数组格式,后端可以直接接收并插入数据库,同时补充错误处理和连接关闭逻辑:
app.post('/upload', async (req, res) => { const client = new MongoClient(URL); try { await client.connect(); const db = client.db('trivia'); // deleteMany需要传空对象,否则会报错 await db.collection('questions').deleteMany({}); // 直接插入数组中的所有数据 await db.collection('questions').insertMany(req.body); console.log('数据上传成功,共插入', req.body.length, '条记录'); res.status(200).json({ success: true, count: req.body.length }); } catch (err) { console.error('数据库操作失败:', err); res.status(500).json({ success: false, error: err.message }); } finally { // 记得关闭数据库连接 await client.close(); } })
总结一下
核心要点就是POST请求的body必须是JSON字符串,而不是JavaScript对象,所以一定要用JSON.stringify()转换后再发送。同时确保请求头Content-Type: application/json和发送的内容格式一致,后端的express.json()中间件就能正确解析请求体了。
备注:内容来源于stack exchange,提问作者AhThe2nd
相关产品推荐
相关产品推荐

