如何使用Node.js解析JSON?

Tik*_*vis 940 javascript json node.js

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

Fel*_*ing 1074

你可以简单地使用JSON.parse.

JSON对象的定义是ECMAScript 5规范的一部分.node.js建立在谷歌Chrome的V8引擎上,符合ECMA标准.因此,node.js也有一个全局对象[docs].JSON

注意 - JSON.parse可以占用当前线程,因为它是一种同步方法.因此,如果您计划解析大型JSON对象,请使用流式json解析器.

  • @snapfractalpop:该文档仅描述了函数等,它们是node.js的一部分.标准JavaScript功能是[V8](http://code.google.com/p/v8/)的一部分,node.js是基于.我相应地更新了答案. (34认同)
  • 没有想到 - 我想我在浏览器中没有做足够的JavaScript ... (3认同)

eli*_*ocs 652

你可以要求 .json文件.

var parsedJSON = require('./file-name');
Run Code Online (Sandbox Code Playgroud)

例如,如果您config.json在源代码文件所在的目录中有一个文件,则可以使用:

var config = require('./config.json');
Run Code Online (Sandbox Code Playgroud)

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

var config = require('./config');
Run Code Online (Sandbox Code Playgroud)

请注意,它require同步的,只读取一次文件,然后调用从缓存中返回结果

另请注意,您应该仅在绝对控制下将其用于本地文件,因为它可能会执行文件中的任何代码.

  • 请注意,响应已缓存.例如,如果你在函数中放置上面的require调用,调用函数,更改JSON文件,再次调用该函数,你将获得JSON文件的*old*版本.几次抓到我了! (94认同)
  • 这种方法只会将文件视为JavaScript,因此可能在.json文件中运行任意代码吗? (29认同)
  • 还要注意`require`是同步的.如果你想异步友好使用`fs.readFile`代替`JSON.parse` (15认同)
  • 简单说明:不要忘记使用`.json`扩展名!如果您的文件没有`.json`扩展名,则require不会将其视为json文件. (15认同)
  • 如果您使用此方法来解析文件,请确保将路径考虑在内.例如,您可能需要执行以下操作:require'./ file-name-with-no-extension'(例如,如果文件位于当前目录中) (4认同)
  • 请记住,需要本地文件(不是依赖项)需要指示它是路径.这就是为什么这个例子以`'./'`开头的原因.`require('config.json')`不起作用. (2认同)

sam*_*ris 310

你可以用JSON.parse().

您应该能够JSON在任何兼容ECMAScript 5的 JavaScript实现上使用该对象.和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);
Run Code Online (Sandbox Code Playgroud)

解析包含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);
});
Run Code Online (Sandbox Code Playgroud)

同步版本

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

你想用require吗?再想想!

您有时可以使用require:

var obj = require('path/to/file.json');
Run Code Online (Sandbox Code Playgroud)

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

  1. require是同步的.如果你有一个非常大的JSON文件,它会阻塞你的事件循环.你真的需要使用JSON.parsefs.readFile.
  2. require读取一次文件.require对同一文件的后续调用将返回缓存副本.如果您想要读取.json不断更新的文件,这不是一个好主意.你可以使用黑客攻击.但在这一点上,它更容易使用fs.
  3. 如果您的文件没有.json扩展名,require则不会将该文件的内容视为JSON.

认真!使用JSON.parse.


load-json-file

如果您正在读取大量.json文件,(如果您非常懒惰),每次编写样板代码都会很烦人.您可以使用该load-json-file模块保存一些字符.

const loadJsonFile = require('load-json-file');
Run Code Online (Sandbox Code Playgroud)

异步版本

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

同步版本

let obj = loadJsonFile.sync('/path/to/file.json');
Run Code Online (Sandbox Code Playgroud)

从流中解析JSON

如果JSON内容通过网络流式传输,则需要使用流式JSON解析器.否则它将占用您的处理器并阻塞您的事件循环,直到JSON内容完全流式传输.

NPM中很多可用的包.选择最适合您的方式.


错误处理/安全性

如果你是什么,如果是通过不确定到JSON.parse()有效的JSON,请确保调用封装到JSON.parse()一个内部try/catch块.用户提供的JSON字符串可能会导致应用程序崩溃,甚至可能导致安全漏洞.如果解析外部提供的JSON,请确保完成错误处理.

  • @natario:我们在这里讨论服务器端JS.假设某人正在解析用户提供的JSON.如果假设JSON始终格式良好,则攻击者可以发送一些格式错误的JSON来触发错误,如果泄漏到客户端,则可能会泄露有关系统的重要信息.或者,如果JSON格式错误并且包含一些带有"<script> ..."的文本,并且错误溢出到客户端,那么您就有一个XSS错误.因此,IMO在解析它时处理JSON错误非常重要. (6认同)
  • 出于好奇,甚至可能导致安全漏洞,怎么样? (2认同)

Mar*_*ahn 81

使用JSON对象:

JSON.parse(str);
Run Code Online (Sandbox Code Playgroud)

  • @DanDascalescu - 如果您注意到,这两个答案是在3年前的同一时间发布的.它们都提供相同的信息.这就是SO的情况,我不打算剔除我的一半答案,因为它们不是公认的答案. (16认同)
  • 这只是重复的答案.请考虑删除它; 你会保留积分. (12认同)
  • 我一个人发现这一系列的评论相当有趣,但答案本身就是浪费我的时间....我不确定这是否意味着应该删除答案,因为那样我就不会看到评论主题.但除此之外,我会说是的. (7认同)
  • @DanDascalescu,我相信这个答案更明确,更直接.被接受的一个没有提供一个用法示例,并且由于许多链接和额外的东西而令人困惑. (7认同)
  • 这个答案有50个赞成票.根据[1%规则](http://en.wikipedia.org/wiki/1%25_rule_%28Internet_culture%29),可能有5000个用户花时间阅读这个答案,这对前一个答案没有任何帮助.它3岁的事实只会让问题变得更糟:) (6认同)

pyp*_*ism 35

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

  • 我喜欢这种方法不要求json文件是应用程序的本地文件.谢谢! (2认同)

Hai*_*der 33

我想提一下全局JSON对象的替代品. JSON.parse并且JSON.stringify都是同步的,所以如果你想处理大对象,你可能想要查看一些异步JSON模块.

看看:https://github.com/joyent/node/wiki/Modules#wiki-parsers-json

  • 哪一个是`async`解析器?我没找到它. (3认同)
  • 链接页面现在标记为"已弃用",并将其自身描述为"褪色文物". (3认同)

Abh*_*rma 30

包括node-fs库.

var fs = require("fs");
var file = JSON.parse(fs.readFileSync("./PATH/data.json", "utf8"));
Run Code Online (Sandbox Code Playgroud)

有关'fs'库的更多信息,请参阅http://nodejs.org/api/fs.html上的文档

  • 或者只是使用回调! (3认同)
  • 值得注意的是,如果您的JSON无法解析或文件不存在,您应该将您的var文件行包装在try/catch中. (2认同)

小智 10

既然你不知道你的字符串实际上是有效的,我会把它放在try catch中.此外,由于try catch块没有被节点优化,我会把整个东西放到另一个函数中:

function tryParseJson(str) {
    try {
        return JSON.parse(str);
    } catch (ex) {
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

或"异步风格"

function tryParseJson(str, callback) {
    process.nextTick(function () {
      try {
          callback(null, JSON.parse(str));
      } catch (ex) {
          callback(ex)
      }
    })
}
Run Code Online (Sandbox Code Playgroud)

  • 我只想说明process.nextTick不是aysnc.它只是推迟读取文件,直到JS事件循环中的下一个函数调用.要异步运行JSON.parse,您必须使用与主Node.js线程不同的线程 (2认同)

Bur*_*gan 8

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

https://github.com/dominictarr/JSONStream


deb*_*ter 6

JSON.parse("your string");
Run Code Online (Sandbox Code Playgroud)

就这样.


Sar*_*tra 6

这里的每个人都讲过JSON.parse,所以我想说点别的.有一个很棒的模块连接许多中间件,使应用程序的开发更容易和更好.其中一个中间件是bodyParser.它解析JSON,html-forms等.还有一个特定的中间件,只用于JSON解析noop.

看看上面的链接,它可能对你很有帮助.


nat*_*n g 6

正如这里提到的其他答案,你可能想要一个你知道安全存在的本地json文件,比如配置文件:

var objectFromRequire = require('path/to/my/config.json'); 
Run Code Online (Sandbox Code Playgroud)

或者使用全局JSON对象将字符串值解析为对象:

var stringContainingJson = '\"json that is obtained from somewhere\"';
var objectFromParse = JSON.parse(stringContainingJson);
Run Code Online (Sandbox Code Playgroud)

请注意,当您需要文件时,将评估该文件的内容,如果它不是json文件而是js文件,则会带来安全风险.

在这里,我发布了一个演示,您可以在其中查看这两种方法并在线播放它们(解析示例位于app.js文件中 - 然后单击运行按钮并在终端中查看结果): http:// staging1 .codefresh.io /实验室/ API/env的/ JSON-解析-示例

你可以修改代码并看到影响......


Nic*_*ele 5

使用JSON进行Node.js的配置?阅读本文并获得超过9000的配置技能......

注意:人们声称data = require('./ data.json'); 是一种安全风险,并以热心的热情贬低人们的答案:你是完全错误的.尝试将非JSON在该文件中...节点会给你一个错误,正是像它会如果用做同样的事情太多阅读速度较慢,难以手工编码文件,然后随后的JSON.parse()来.请停止传播错误信息; 你在伤害世界,没有帮助.节点的设计允许这样做; 这不是安全风险!

适当的应用程序有3 以上的配置:

  1. 服务器/容器配置
  2. 应用程序配置
  3. (可选)租户/社区/组织配置
  4. 用户配置

大多数开发人员将其服务器和应用程序配置视为可以更改.它不能.您可以将更高层的更改层叠在一起,但是您正在修改基本要求.有些事情需要存在!让你的配置表现得像它是不可变的,因为它的一些基本上就像你的源代码一样.

没有看到很多你的东西在启动后不会改变导致反模式,比如乱丢你的配置加载try/catch块,假装你可以在没有正确设置应用程序的情况下继续.你不能.如果可以,那属于社区/用户配置层,而不是服务器/应用配置层.你做错了.当应用程序完成引导程序时,可选的东西应该在顶部分层.

停止将头撞在墙上:你的配置应该非常简单.

看一下使用简单的json配置文件和简单的app.js文件设置与协议无关和数据源无关的服务框架这样复杂的东西是多么容易......

容器config.js ...

{
    "service": {
        "type"  : "http",
        "name"  : "login",
        "port"  : 8085
    },
    "data": {
        "type"  : "mysql",
        "host"  : "localhost",
        "user"  : "notRoot",
        "pass"  : "oober1337",
        "name"  : "connect"
    }
}
Run Code Online (Sandbox Code Playgroud)

index.js ...(为一切提供动力的引擎)

var config      = require('./container-config.json');       // Get our service configuration.
var data        = require(config.data.type);            // Load our data source plugin ('npm install mysql' for mysql).
var service     = require(config.service.type);         // Load our service plugin ('http' is built-in to node).
var processor   = require('./app.js');                  // Load our processor (the code you write).

var connection  = data.createConnection({ host: config.data.host, user: config.data.user, password: config.data.pass, database: config.data.name });
var server      = service.createServer(processor);
connection.connect();
server.listen(config.service.port, function() { console.log("%s service listening on port %s", config.service.type, config.service.port); });
Run Code Online (Sandbox Code Playgroud)

app.js ...(为协议不可知和数据源不可知服务提供支持的代码)

module.exports = function(request, response){
    response.end('Responding to: ' + request.url);
}
Run Code Online (Sandbox Code Playgroud)

使用此模式,您现在可以在启动的应用程序之上加载社区和用户配置内容,dev ops已准备好将您的工作推送到容器中并进行扩展.你读过多租户.Userland是孤立的.您现在可以分离您正在使用的服务协议的关注点,您正在使用的数据库类型,并专注于编写好的代码.

因为你正在使用图层,所以你可以随时依赖单一事实来源(分层配置对象),并避免每一步都进行错误检查,担心"哦废话,我怎么做这个没有正确配置的工作?!?".


Man*_*lon 5

如果您需要以安全的方式使用 Node.js 解析 JSON(又名:用户可以输入数据或公共 API),我建议使用secure-json-parse

用法与默认值类似JSON.parse,但它将保护您的代码免受以下影响:

const badJson = '{ "a": 5, "b": 6, "__proto__": { "x": 7 }, "constructor": {"prototype": {"bar": "baz"} } }'

const infected = JSON.parse(badJson)
console.log(infected.x) // print undefined

const x = Object.assign({}, infected)
console.log(x.x) // print 7

const sjson = require('secure-json-parse')
console.log(sjson.parse(badJson)) // it will throw by default, you can ignore malicious data also
Run Code Online (Sandbox Code Playgroud)