这让我发疯了。我不知道为什么,但当我使用文件系统require('fs')
读取有效的Json文件时,我得到错误:无效的json。这是代码:
var fs = require('fs');
const FILE_NAME = './json.json'
/*
// This way it works!
var jsonData = require('./json.json')
console.log(jsonData);
*/
async function readFile(filePath){
return new Promise(function(resolve, reject){
fs.readFile(filePath, 'utf8', function(err, contents) {
if(err){
console.log("Cant read the file " + err);
reject(err)
}
else{
resolve(contents)
}
})
})
}
async function getNames(fileName){
readFile(fileName).then(function(data){
try {
console.log(`Type of data: ` + typeof data);
console.log("File data: " + data);
return JSON.parse(data);
} catch (error) {
throw new Error( "Invalid JSON: " + error);
}
}).then(function(data){
console.log(`FILE OBJECT: ` + data);
}).catch(function(err){
console.error(err);
})
}
getNames(FILE_NAME)
这是文件内容:
{
"name": "riko"
}
这是控制台输出:
Type of data: string
File data: {
"name": "riko"
}
Error: Invalid JSON: SyntaxError: Unexpected token in JSON at position 0
at C:\Users\rojer\Desktop\Node\test\main.js:31:13
我知道我可以使用var jsonData = require('./json.json')
,但是
似乎有些垃圾。
请帮忙。
这个:
Error: Invalid JSON: SyntaxError: Unexpected token in JSON at position 0 at C:\Users\rojer\Desktop\Node\test\main.js:31:13
告诉我们文件的开头有一个看不见的字符,可能是byte order mark (BOM),require
正在处理,但你的代码不是。如果文件确实是UTF-8,则该BOM将为\xEF\xBB\xBF
。一旦将UTF-8读入JavaScript字符串,那将是代码点\u{FEFF}
(因为JavaScript字符串是UTF-16 [但是容忍无效的代理对])。更新:您的二进制列表确认了这一点。
我可以确认,如果我有一个带有BOM的UTF-8 JSON文件,require
会读取它并处理BOM,但readFile
会返回BOM的内容,其中BOM完好无损,这会使JSON.parse
上升。
您可以检查BOM并将其剥离,请参阅***
行:
const UTF8_BOM = "\u{FEFF}"; // ***
async function getNames(fileName){
readFile(fileName).then(function(data){
try {
console.log(`Type of data: ` + typeof data);
if (data.startsWith(UTF8_BOM)) { // ***
data = data.substring(UTF8_BOM.length); // ***
}
console.log("File data: " + data);
return JSON.parse(data);
} catch (error) {
throw new Error( "Invalid JSON: " + error);
}
}).then(function(data){
console.log(`FILE OBJECT: ` + data);
}).catch(function(err){
console.error(err);
})
}
或者,如果您不想要BOM,这里有一个快速而又脏的工具来添加/删除UTF-8文件上的BOM:
const fs = require("fs");
const UTF8_BOM = "\u{FEFF}";
const actions = new Map([
["-a", addBOM],
["-r", removeBOM],
["-t", toggleBOM]
]);
main();
function main() {
const filename = process.argv[2];
const option = process.argv[3] || "-t";
const action = actions.get(option);
if (!filename) {
help();
return;
}
if (!action) {
console.error(`Invalid option ${option}`);
help();
return;
}
fs.readFile(filename, 'utf-8', (err, data) => {
if (err) {
console.error(`${filename}: Error reading file: ${err}`);
return;
}
const hasBOM = data.startsWith(UTF8_BOM);
action(filename, data, hasBOM);
});
}
function writeResult(filename, data, toggle, successMessage, failMessage) {
fs.writeFile(filename, data, "utf-8", (err) => {
if (err) {
console.error(`${filename}: ${failMessage}: ${err}`);
} else {
console.log(`${filename}: ${successMessage}${toggle ? " (toggled)" : ""}`);
}
});
}
function addBOM(filename, data, hasBOM, toggle) {
if (hasBOM) {
console.log(`${filename}: Already has a BOM`);
} else {
writeResult(filename, UTF8_BOM + data, toggle, "Added BOM", "Error adding BOM");
}
}
function removeBOM(filename, data, hasBOM, toggle) {
if (!hasBOM) {
console.log(`${filename}: Already doesn't have a BOM`);
} else {
writeResult(filename, data.substring(UTF8_BOM.length), toggle, "Removed BOM", "Error removing BOM");
}
}
function toggleBOM(filename, data, hasBOM) {
if (hasBOM) {
removeBOM(filename, data, hasBOM, true);
} else {
addBOM(filename, data, hasBOM, true);
}
}
function help() {
console.log("Usage: node utf8bomtoggle [filename] {options}");
console.log("{options} can be:");
console.log(" -t Toggle a BOM [default]");
console.log(" -a Add a BOM if not present");
console.log(" -r Remove a BOM if present");
}