使用Node.js如何解析JSON?

1030

我应该如何使用Node.js解析JSON?有没有一些模块可以安全地验证和解析JSON?

31个回答

1141

有人知道为什么它不在官方文档中吗?或者,如果在的话,应该在哪里找到? - snapfractalpop
35
这份文档仅描述了属于node.js一部分的函数等内容。标准JavaScript功能是构建在node.js之上的V8中的。我已相应地更新了答案。 - Felix Kling
1
@FelixKling 说句实话,这里有很多关于Node的Github Wiki上的内容:https://github.com/joyent/node/wiki/ECMA-5-Mozilla-Features-Implemented-in-V8 - damianb
这里,我已经发布了一个演示,您可以在线查看和玩弄这个答案(解析示例在app.js文件中 - 然后单击运行按钮,在终端中查看结果):[链接](http://staging1.codefresh.io/labs/api/env/json-parse-example)您可以修改代码并查看影响... - nathan g
你的答案需要先了解 JavaScript 语法。能否给出一个使用示例呢? JSON.parse(str); // 是最适合新手的,因此更好的答案。 - webb
显示剩余2条评论

679

你可以使用require方法来加载.json文件。

var parsedJSON = require('./file-name');
例如,如果您在源代码文件所在的同一目录中有一个名为config.json的文件,您将使用以下内容:

var config = require('./config.json');

或者(文件扩展名可以省略):

var config = require('./config');

请注意require同步的,仅会读取文件一次,随后的调用将返回缓存中的结果。

同时请注意,您应仅在绝对控制之下的本地文件中使用此方法,因为它可能执行文件中的任何代码。


4
如果您使用此方法来解析文件,请确保考虑到文件路径以进行require。例如,您可能需要执行类似以下的操作:require './没有扩展名的文件名'(例如,如果文件在当前目录中)。 - SnapShot
96
请注意,响应是被缓存的。例如,如果您将上述require调用放在一个函数中,调用该函数,更改JSON文件,然后再次调用该函数,您将获得JSON文件的版本。这已经让我犯了几次错误! - Ben Clayton
15
请注意,require 方法是同步的。如果您需要使用异步方式,请改用 fs.readFile 方法,并在其后使用 JSON.parse 方法。 - Evan Moran
29
这种方法是否只会将文件视为 JavaScript,从而可能在 .json 文件中运行任意代码? - d11wtq
15
简要说明:不要忘记使用“.json”扩展名!如果您的文件没有“.json”扩展名,require将不会将其视为json文件。 - Jason
显示剩余11条评论

341

你可以使用JSON.parse()

你应该能够在任何符合ECMAScript 5标准的JavaScript实现中使用JSON对象。而V8,它是Node.js构建所基于的之一。

注意:如果你正在使用JSON文件来存储敏感信息(例如密码),那么这样做是错误的。查看Heroku如何处理:https://devcenter.heroku.com/articles/config-vars#setting-up-config-vars-for-a-deployed-application。了解你的平台如何处理,并使用process.env从代码内检索配置变量。


解析包含JSON数据的字符串

var str = '{ "name": "John Doe", "age": 42 }';
var obj = JSON.parse(str);

解析包含JSON数据的文件

您需要使用fs模块进行一些文件操作。

异步版本


var fs = require('fs');

fs.readFile('/path/to/file.json', 'utf8', function (err, data) {
    if (err) throw err; // we'll not consider error handling for now
    var obj = JSON.parse(data);
});

同步版本

var fs = require('fs');
var json = JSON.parse(fs.readFileSync('/path/to/file.json', 'utf8'));

你想使用require吗?再三考虑!

有时候可以使用require

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

但是,出于几个原因,我不建议这样做:

  1. require 是同步的。如果你有一个非常大的 JSON 文件,它会阻塞你的事件循环。你真的需要使用 JSON.parsefs.readFile
  2. require 只会读取文件一次。对于相同文件的后续调用,require 将返回一个缓存的副本。如果你想读取一个不断更新的 .json 文件,这不是一个好主意。你可以使用hack。但现在,最简单的方法是使用 fs
  3. 如果你的文件没有 .json 扩展名,require 将不把文件内容视为 JSON。

认真点!使用 JSON.parse


load-json-file 模块

如果你正在读取大量的 .json 文件(并且如果你非常懒),每次编写样板代码都会变得很烦人。你可以使用load-json-file 模块来节省一些字符。

const loadJsonFile = require('load-json-file');

异步版本

loadJsonFile('/path/to/file.json').then(json => {
    // `json` contains the parsed object
});

同步版本

let obj = loadJsonFile.sync('/path/to/file.json');

从流中解析JSON

如果JSON内容在网络上以流的形式传输,需要使用流式 JSON 解析器。否则它会占用处理器并阻塞事件循环,直到JSON内容完全传输。

在NPM中有许多可用的软件包可供选择,选择最适合您的软件包。


错误处理/安全性

如果不确定传递给JSON.parse()的内容是否是有效的JSON,请务必将对JSON.parse()的调用放置在try/catch块中。用户提供的JSON字符串可能会导致应用程序崩溃,甚至可能导致安全漏洞。确保在解析外部提供的JSON时进行错误处理。


2
出于好奇,这会导致什么安全漏洞? - natario
6
我们在谈论服务器端的 JavaScript。假设有人正在解析用户提供的 JSON 数据。如果假设这个 JSON 数据总是格式正确的,那么攻击者可以发送一些格式不正确的 JSON 数据来触发错误,如果这些错误被泄露到客户端,可能会泄露关于系统的重要信息。或者如果这个 JSON 数据既格式不正确又包含一些 <script>...</script> 文本,并且错误被泄露到客户端,那么就会出现 XSS 漏洞。因此,在解析 JSON 数据时及时处理错误非常重要。 - sampathsris
1
@NickSteele:然而,我将“this is not recommended”更改为“I do not recommend”。希望你现在满意。 - sampathsris
1
@NickSteele:鉴于我列出的缺陷,我认为这不是一个设计良好的功能。在我看来,有些人认为“嘿,使用require包含JSON会很酷”,甚至没有费心记录副作用。这也意味着require接受两种语言的文件:JavaScript和JSON(它们不同)。SRP就这样了。 - sampathsris
1
@NickSteele:是的,仅用于配置时它可以正常工作。但是JSON并不仅仅用于配置。 - sampathsris
显示剩余7条评论

87

12
这个回答只是重复了顶部的答案。请考虑删除它,您将保留积分。 - Dan Dascalescu
6
这个回答获得了50个赞。根据“1%规则”,可能有5000个用户花时间阅读了这个回答,但对排名第一的答案没有任何帮助。而且它已经发布了3年,这使问题变得更加严重 :) - Dan Dascalescu
17
如果您注意到,两个答案是在3年前完全同时发布的。它们都提供了相同的信息。这种情况在 SO 上随处可见,我不会仅仅因为它们没有被采纳就删除一半的回答。 - user578895
8
我发现这一系列的评论很有意思,但回答本身让我感到浪费时间。...我不确定这是否意味着应该删除答案,因为那样我就看不到评论线程了。但除此之外,我想说是的。 - MalcolmOcean
7
@DanDascalescu,我认为这个答案更清晰直截了当。被接受的回答没有给出用法示例,并且由于有许多链接和额外的内容而令人困惑。 - andresgottlieb
显示剩余5条评论

37

JSON.parse 的另一个示例:

var fs = require('fs');
var file = __dirname + '/config.json';

fs.readFile(file, 'utf8', function (err, data) {
  if (err) {
    console.log('Error: ' + err);
    return;
  }

  data = JSON.parse(data);

  console.dir(data);
});

2
我喜欢这种方法不需要将json文件放在应用程序本地。谢谢! - Charles Brandt

35

1
如果期望从传入连接中获取JSON数据,这一点尤其重要。如果JSON.parse解析到格式不正确的JSON数据,整个应用程序将会崩溃;或者使用process.on('uncaughtException', function(err) { ... });,最终将无法向用户发送“格式不正确的JSON”错误信息。 - Paul
3
哪个是“async”解析器?我没有找到它。 - bxshi
3
该链接页面现在被标记为“已弃用”,并自称为“褪色的遗迹”。 - nobody

30

引入node-fs库。

var fs = require("fs");
var file = JSON.parse(fs.readFileSync("./PATH/data.json", "utf8"));

要了解更多关于 'fs' 库的信息,请参考http://nodejs.org/api/fs.html上的文档。


2
值得注意的是,你应该在 var 文件行中加入 try/catch,以防 JSON 解析失败或文件不存在。 - Fostah
3
或者只需使用回调函数! - lawx

12

既然您不知道您的字符串是否有效,我建议您首先放入try catch中。另外,由于node不会对try catch块进行优化,我建议您将整个操作放入另一个函数中:

function tryParseJson(str) {
    try {
        return JSON.parse(str);
    } catch (ex) {
        return null;
    }
}

"异步样式"中的OR

function tryParseJson(str, callback) {
    process.nextTick(function () {
      try {
          callback(null, JSON.parse(str));
      } catch (ex) {
          callback(ex)
      }
    })
}

2
我只想指出process.nextTick不是异步的。它只是推迟读取文件,直到JS事件循环中的下一个函数调用。要异步运行JSON.parse,您必须使用与主Node.js线程不同的线程。 - Alexander Mills

9
解析JSON流?使用JSONStream
var request = require('request')
  , JSONStream = require('JSONStream')

request({url: 'http://isaacs.couchone.com/registry/_all_docs'})
    .pipe(JSONStream.parse('rows.*'))
    .pipe(es.mapSync(function (data) {
      return data
    }))

https://github.com/dominictarr/JSONStream


7
JSON.parse("your string");

就这些。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接