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

Mat*_*att 550 javascript json node.js

背景

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

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

mih*_*hai 1106

同步:

var fs = require('fs');
var obj = JSON.parse(fs.readFileSync('file', 'utf8'));
Run Code Online (Sandbox Code Playgroud)

异步:

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

  • 为了完整起见.它们存在一个名为[jsonfile]的npm(https://www.npmjs.com/package/jsonfile). (21认同)
  • 我认为JSON.parse是同步的,它直接来自v8,这意味着即使使用Async方式,人们也必须小心使用大型JSON文件.因为它会占用节点. (12认同)
  • 两点:(1)同步答案应该是`let imported = require("file.json")`.(2)JSON.parse必须是异步的,因为我使用此代码将70mb JSON文件作为对象加载到内存中.这种方式需要几毫秒,但如果我使用`require()`,它就是_chugs_. (5认同)
  • 对于在2019年及以后找到此答案的人来说,Node.js通过`require`对许多版本提供了本地json支持,如果您只想加载json文件,则此答案不再适用。只需使用`let data = require('./ yourjsonfile.json')`即可结束(带书注,如果require的性能正在影响您的代码,则除了“想要加载.json文件”之外,您还有很多其他问题。 ) (5认同)
  • 我不敢相信找到这么简单的事情是如此困难.我从谷歌得到的每个答案都是在做HTTPRequest或使用JQuery或在浏览器中进行 (4认同)
  • 还有一点:这是异步的,但不是_streaming_。为此,您需要一个库(例如Oboe.js)。区别在于异步不会阻塞您的执行线程,但是除非您正在进行流传输,否则仍然会看到大量的内存消耗高峰(例如450mb的内存用于处理70mb的JSON文件)。 (2认同)
  • @KyleBaker`JSON.parse`是同步的。`require`比JSON.parse更多。JSON.parse只是解析JSON。`require`正在解析JavaScript。我相信您可以弄清楚为什么后者要慢一些。 (2认同)

Tra*_*ell 369

我发现这样做的最简单方法是使用require和JSON文件的路径.

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

test.json

{
  "firstName": "Joe",
  "lastName": "Smith"
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用在.atn.js应用程序中轻松加载它 require

var config = require('./test.json');
console.log(config.firstName + ' ' + config.lastName);
Run Code Online (Sandbox Code Playgroud)

  • 大家都知道,如果我没记错的话,节点中的`require`会同步运行.深入潜水[这里](http://fredkschott.com/post/2014/06/require-and-the-module-system/) (32认同)
  • 这种方法的另一个问题是,除非您专门删除缓存的实例,否则缓存所需的数据 (16认同)
  • "require"用于在应用程序的整个生命周期内加载您正在使用的模块或配置文件.使用它来加载文件似乎不对. (12认同)
  • 对于小型 DevOps 脚本或批量操作来说,这是一个完善的解决方案。您必须平衡人类时间与绩效。就您可以记住并在这些适当情况下快速使用的东西而言,这是最好的。并非每项任务都涉及大数据™和恶劣的执行环境。 (4认同)
  • 我想说这可能是安全威胁。如果您要加载的json文件包含JS代码,“需要”该代码运行该代码吗?如果是这样,那么您确实需要控制json文件的来源,否则攻击者可能会在您的计算机上运行恶意代码。 (2认同)
  • @gvmani 到底是什么样的安全问题?我粗略的实验表明没有代码被执行。然后,[这里](https://github.com/nodejs/node/blob/v15.4.0/lib/internal/modules/cjs/loader.js#L1143-L1151)加载json文件的部分。`JSONParse` 可能是通过[复制 `JSON.parse` 函数获得的](https://github.com/nodejs/node/blob/v15.4.0/lib/internal/per_context/primordials.js#L125-L129) 。所以我想说,可以安全地假设需要 json 文件在安全方面是可以的(什么都不执行)。 (2认同)

Flo*_*ine 56

异步是有原因的!在@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
}
Run Code Online (Sandbox Code Playgroud)

  • 同意:),同样添加异步 (9认同)
  • 这是有原因的..除非你想要它同步. (7认同)

Ale*_*des 37

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

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

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

  • 此方法仅加载文件一次.如果你在新的require之后更改`file.json`(没有重启程序),数据将来自第一次加载.我没有消息来支持这个,但我在app中建立了这个 (4认同)
  • @ DavidA.Gray该问题希望能够将对象作为对象而不是字符串进行访问。卢卡斯(Lukas)的单身人士中提到的这个答案很好。 (3认同)
  • 使用 require 还将执行文件中的任意代码。这种方法是不安全的,我建议不要使用它。 (3认同)

J P*_*J P 15

在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
  })
Run Code Online (Sandbox Code Playgroud)

  • `.readFile`已经异步,如果你正在寻找同步版本,它的名字是`.readFileSync`. (3认同)

Flo*_*ann 9

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

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

import { readFile } from 'fs/promises';

let data = JSON.parse(await readFile("filename.json", "utf8"));
Run Code Online (Sandbox Code Playgroud)

try/catch根据需要添加一个块来处理异常。

  • 为什么不使用“readFileSync”并删除“await”?`JSON.parse(readFileSync("filename.json", "utf8"));` (2认同)

Sum*_*tra 7

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

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

readJsonFile() // prints your json object
Run Code Online (Sandbox Code Playgroud)


Art*_*aca 6

使用fs-extra包非常简单:

同步:

const fs = require('fs-extra')

const packageObj = fs.readJsonSync('./package.json')
console.log(packageObj.version) 
Run Code Online (Sandbox Code Playgroud)

异步:

const fs = require('fs-extra')

const packageObj = await fs.readJson('./package.json')
console.log(packageObj.version) 
Run Code Online (Sandbox Code Playgroud)


Ani*_*mar 5

2023 年的答案,使用导入属性

import jsObject from "./test.json" assert {type: "json"};
console.log(jsObject)
Run Code Online (Sandbox Code Playgroud)

动态导入

const jsObject = await import("./test.json", {assert: {type: "json"}});
console.log(jsObject);
Run Code Online (Sandbox Code Playgroud)

更多信息:tc39 /提案导入属性