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

读取本地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对象的数组:[{}, {}, {}]。


问题分析&解决方案

其实你遇到的问题核心很明确:

  1. Unexpected token o错误原因:你把已经解析成JavaScript对象的data直接放到了body里,但fetch不会自动把JS对象转成JSON字符串——它会把对象转成[object Object]这种无效的JSON格式,后端用express.json()解析时自然会报错。
  2. 空请求体问题:大多是因为请求头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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 14:14:39