ChatGPT解决这个技术问题 Extra ChatGPT

使用 Node.JS,如何将 JSON 文件读入(服务器)内存?

背景

我正在对 Node.js 进行一些实验,并且想从文本文件或 .js 文件(哪个更好??)中读取 JSON 对象到内存中,以便我可以从代码中快速访问该对象。我意识到那里有诸如 Mongo、Alfred 之类的东西,但这不是我现在需要的。

问题

如何使用 JavaScript/Node 从文本或 js 文件中读取 JSON 对象并进入服务器内存?


m
mihai

同步:

var fs = require('fs');
var obj = JSON.parse(fs.readFileSync('file', 'utf8'));

异步:

var fs = require('fs');
var obj;
fs.readFile('file', 'utf8', function (err, data) {
  if (err) throw err;
  obj = JSON.parse(data);
});

我认为 JSON.parse 是同步的,它直接来自 v8,这意味着即使使用异步方式,人们也必须小心处理大型 JSON 文件。因为它会占用节点。
为了完整起见。他们存在一个名为 jsonfile 的 npm。
我不敢相信找到这个简单的东西是如此困难。我从谷歌得到的每一个答案都是在做一个 HTTPRequest 或使用 JQuery 或在浏览器中做
两点:(1)同步答案应该只是let imported = require("file.json")。 (2) JSON.parse 必须是异步的,因为我使用这段代码将一个 70mb 的 JSON 文件作为对象加载到内存中。这种方式需要几毫秒,但如果我使用 require(),它会chugs
对于在 2019 年及以后找到此答案的人,Node.js 已经通过 require 为许多许多版本提供原生 json 支持,如果您只想加载 json 文件,则此答案不再适用。只需使用 let data = require('./yourjsonfile.json') 就可以了(附注,如果 require 的性能影响您的代码,那么您遇到的问题远远超出“想要加载 .json 文件”)
T
Travis Tidwell

我发现最简单的方法是使用 require 和 JSON 文件的路径。

例如,假设您有以下 JSON 文件。

测试.json

{
  "firstName": "Joe",
  "lastName": "Smith"
}

然后,您可以使用 require 轻松地将其加载到您的 node.js 应用程序中

var config = require('./test.json');
console.log(config.firstName + ' ' + config.lastName);

众所周知,如果我没记错的话,节点中的 require 是同步运行的。深入了解here
这种方法的另一个问题/好处是,除非您专门删除缓存的实例,否则所需的数据会被缓存
“require”用于加载您在应用程序的整个生命周期中使用的模块或配置文件。使用它来加载文件似乎不正确。
我会说这可能是一个安全威胁。如果您正在加载的 json 文件包含 JS 代码,它会require运行该代码吗?如果是这样,那么您确实需要控制 json 文件的来源,否则攻击者可能会在您的计算机上运行恶意代码。
对于小型 DevOps 脚本或批处理操作,这是一个不错的解决方案。你必须平衡人力时间和性能。至于您可以在这些适当的情况下记住并快速使用的东西,这是最重要的。并非每项任务都涉及 Big Data™ 和敌对的执行环境。
F
Florian Margaine

异步是有原因的!向@mihai 扔石头

否则,这是他在异步版本中使用的代码:

// Declare variables
var fs = require('fs'),
    obj

// Read the file and send to the callback
fs.readFile('path/to/file', handleFile)

// Write the callback function
function handleFile(err, data) {
    if (err) throw err
    obj = JSON.parse(data)
    // You can now play with your datas
}

同意:),也添加了异步
太好了 :-) 我不喜欢内联回调,它可能导致我宁愿避免的回调噩梦。
它的存在是有原因的......除非你想要它同步。
A
Alex Eftimiades

至少在 Node v8.9.1 中,你可以这样做

var json_data = require('/path/to/local/file.json');

并访问 JSON 对象的所有元素。


这种方法只加载一次文件。如果您将在新要求(无需重新启动程序)之后更改 file.json,数据将从第一次加载开始。我没有资源支持这一点,但我在我正在构建的应用程序中有这个
您的回答非常不完整。得到的是一个对象,它甚至不需要实现 tostring()。
@DavidA.Gray 问题希望能够将对象作为对象访问,而不是作为字符串访问。除了单身问题卢卡斯提到这个答案很好。
使用 require 也会执行文件中的任意代码。这种方法不安全,我建议不要这样做。
F
Florian Ledermann

2022 年的答案,使用 ES6 模块语法和 async/await

在现代 JavaScript 中,这可以一次性完成,无需安装额外的包:

import { readFile } from 'fs/promises';

let data = JSON.parse(await readFile("filename.json", "utf8"));

添加 try/catch 块以根据需要处理异常。


你会把try catch放在哪里?
我正在找这个,谢谢!当我知道文件的内容是 JSON 数据时效果很好,但扩展名是自定义的。在这种情况下不能使用通常的 require('./jsonfile.xyz')
j
jpsecher

在 Node 8 中,您可以使用内置的 util.promisify() 来异步读取这样的文件

const {promisify} = require('util')
const fs = require('fs')
const readFileAsync = promisify(fs.readFile)

readFileAsync(`${__dirname}/my.json`, {encoding: 'utf8'})
  .then(contents => {
    const obj = JSON.parse(contents)
    console.log(obj)
  })
  .catch(error => {
    throw error
  })

.readFile 已经是异步的,如果您正在寻找同步版本,它的名称是 .readFileSync
如果您想使用 Promise,从 Node 10 开始还有 fs/promises。注意:API 是实验性的:nodejs.org/api/fs.html#fs_fs_promises_api
@Aternus .readFile异步,但不是 async。意思是,该函数没有用 async 关键字定义,也没有返回 Promise,所以你不能做 await fs.readFile('whatever.json');
@Kip CodeSandBox 怎么样?
A
Arturo Menchaca

使用 fs-extra 包非常简单:

同步:

const fs = require('fs-extra')

const packageObj = fs.readJsonSync('./package.json')
console.log(packageObj.version) 

异步:

const fs = require('fs-extra')

const packageObj = await fs.readJson('./package.json')
console.log(packageObj.version) 

i
ifelse.codes

使用 node-fs-extra (异步等待)

const readJsonFile = async () => {
    const myJsonObject = await fs.readJson('./my_json_file.json');
    console.log(myJsonObject);
}

readJsonFile() // prints your json object

x
xgqfrms

https://nodejs.org/dist/latest-v6.x/docs/api/fs.html#fs_fs_readfile_file_options_callback

var fs = require('fs');  

fs.readFile('/etc/passwd', (err, data) => {
  if (err) throw err;
  console.log(data);
});  

// options
fs.readFile('/etc/passwd', 'utf8', callback);

https://nodejs.org/dist/latest-v6.x/docs/api/fs.html#fs_fs_readfilesync_file_options

您可以在文件系统文档中找到 Node.js 的所有用法!希望这对你有帮助!


O
Oliver Salzburg
function parseIt(){
    return new Promise(function(res){
        try{
            var fs = require('fs');
            const dirPath = 'K:\\merge-xml-junit\\xml-results\\master.json';
            fs.readFile(dirPath,'utf8',function(err,data){
                if(err) throw err;
                res(data);
        })}
        catch(err){
            res(err);
        }
    });
}

async function test(){
    jsonData = await parseIt();
    var parsedJSON = JSON.parse(jsonData);
    var testSuite = parsedJSON['testsuites']['testsuite'];
    console.log(testSuite);
}

test();

J
Jehy

这么多的答案,没有人做过基准来比较同步、异步和需要。我描述了通过 require、readFileSync 和 readFile here 在内存中读取 json 的用例的区别。


H
Hitesh Sahu

如果您正在寻找一个完整的解决方案,用于 Async 通过错误处理从 Relative Path 加载 JSON 文件

  // Global variables
  // Request path module for relative path
    const path = require('path')
  // Request File System Module
   var fs = require('fs');


// GET request for the /list_user page.
router.get('/listUsers', function (req, res) {
   console.log("Got a GET request for list of users");

     // Create a relative path URL
    let reqPath = path.join(__dirname, '../mock/users.json');

    //Read JSON from relative path of this file
    fs.readFile(reqPath , 'utf8', function (err, data) {
        //Handle Error
       if(!err) {
         //Handle Success
          console.log("Success"+data);
         // Parse Data to JSON OR
          var jsonObj = JSON.parse(data)
         //Send back as Response
          res.end( data );
        }else {
           //Handle Error
           res.end("Error: "+err )
        }
   });
})

目录结构:

https://i.stack.imgur.com/Bz7jB.png