使用“fs”读取JSON文件会抛出“无效的json”Node.js

问题描述 投票:1回答:1

这让我发疯了。我不知道为什么,但当我使用文件系统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'),但是

  1. 我想知道它不起作用的原因。
  2. 如果JSON数据嵌入在常规文本文件中的某个位置,该怎么办?

enter image description here

似乎有些垃圾。

enter image description here

请帮忙。

javascript node.js json
1个回答
2
投票

这个:

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");
}
© www.soinside.com 2019 - 2024. All rights reserved.