NodeJS读取JSON数据调用天气API出现JSON.parse错误如何解决
问题原因
你遇到的SyntaxError: Unexpected token in JSON at position 0错误,核心是JSON.parse接收到的内容不是合法JSON格式,首个字符就不符合JSON语法规范,对应你给出的代码场景,有几个常见的触发原因和修复方案:
修复方案
1. 处理JSON文件BOM头问题
绝大多数这类首字符解析错误都是UTF-8格式的JSON文件携带了BOM(字节顺序标记)导致的,Windows平台的编辑器保存文件时经常默认添加BOM,这个不可见的标记会被识别为位置0的非法字符。
直接修改解析逻辑即可,将代码里的
data2 = JSON.parse(data);
替换为:
// 先移除可能存在的BOM头再解析 data2 = JSON.parse(data.replace(/^\uFEFF/, ''));
也可以直接用编辑器将JSON文件另存为「UTF-8 无BOM」格式,从根源解决问题。
2. 排查文件读取异常
在解析前添加日志确认读取到的内容是否正确,避免因为路径错误读取到空内容或者其他文件的内容:
if(err) throw err; // 新增日志确认读取内容 console.log('读取到的文件内容:', data); data2 = JSON.parse(data.replace(/^\uFEFF/, ''));
如果日志输出为空或者和你写的JSON内容不符,说明文件路径配置错误:NodeJS里相对路径是相对于执行node命令的工作目录,而非JS文件所在目录,建议换成绝对路径读取:
// 先引入path模块 const path = require('path'); // 读取时用绝对路径 fs.readFile(path.resolve(__dirname, './json/data.json'),"utf8", function (err, data) { // 原有逻辑 })
3. 修复代码里的其他逻辑问题
你当前的代码还有异步处理、API返回值解析的问题,建议一并修复:
- 你用了
async声明函数,但全程没有用await处理异步逻辑,最后console.log(lstValid)执行时,文件还没读取完成、API请求也没有返回,所以你会先看到空数组[]的输出 - OpenWeatherMap的返回结果里
weather字段是数组,你写的data.weather.description会取值失败,要改成data.weather[0].description
修正后的参考代码:
const fs = require('fs/promises'); // 改用 promise 版的fs模块更适配async语法 const path = require('path'); async function calcWeather() { const lstValid = []; try { // await 等待文件读取完成 const data = await fs.readFile(path.resolve(__dirname, './json/data.json'), 'utf8'); const data2 = JSON.parse(data.replace(/^\uFEFF/, '')); // 等待所有API请求完成 const requestPromises = data2.map(async item => { const base = `https://api.openweathermap.org/data/2.5/weather?lat=${item.latjson}&lon=${item.lonjson}&appid=${api_key}&units=metric&lang=sp`; const response = await fetch(base); const weatherData = await response.json(); const myObject = { Id_Oficina: item.IdOficina, Humedad: weatherData.main.humidity, Nubes: weatherData.clouds.all, Sensacion: weatherData.main.feels_like, Temperatura: weatherData.main.temp, Descripcion: weatherData.weather[0].description, // 修正weather字段取值 }; if (myObject.Temperatura < 99) { lstValid.push(myObject); } }); await Promise.all(requestPromises); console.log(lstValid); // 所有请求完成后再输出结果 return lstValid; } catch (err) { console.error('处理失败:', err); throw err; } }
内容的提问来源于stack exchange,提问作者Martín JF
相关产品推荐
相关产品推荐

