How to parse JSON using Node.js?
我应该如何使用node.js解析JSON?是否有一些模块可以安全地验证和解析JSON?
您只需使用
注-
您可以需要.json文件。
1 | var parsedJSON = require('./file-name'); |
例如,如果您在与源代码文件相同的目录中有一个
1 | var config = require('./config.json'); |
或(文件扩展名可以省略):
1 | var config = require('./config'); |
注意,
另外请注意,您应该只将其用于受绝对控制的本地文件,因为它可能执行文件中的任何代码。
您可以使用
您应该能够在任何ECMAScript 5兼容的javascript实现上使用
Note: If you're using a JSON file to store sensitive information (e.g. passwords), that's the wrong way to do it. See how Heroku does it: https://devcenter.heroku.com/articles/config-vars#setting-up-config-vars-for-a-deployed-application. Find out how your platform does it, and use
process.env to retrieve the config vars from within the code.
分析包含JSON数据的字符串
1 2 | var str = '{"name":"John Doe","age": 42 }'; var obj = JSON.parse(str); |
分析包含JSON数据的文件
您必须使用
1 2 3 4 5 6 | 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); }); |
同步版本
1 2 | var fs = require('fs'); var json = JSON.parse(fs.readFileSync('/path/to/file.json', 'utf8')); |
你想用
有时可以使用
1 | var obj = require('path/to/file.json'); |
但是,我不建议这样做的原因有几个:
说真的!使用
如果您正在读取大量的
1 | const loadJsonFile = require('load-json-file'); |
异步版本
1 2 3 | loadJsonFile('/path/to/file.json').then(json => { // `json` contains the parsed object }); |
同步版本
1 | let obj = loadJsonFile.sync('/path/to/file.json'); |
从流分析JSON
如果JSON内容通过网络传输,则需要使用流式JSON解析器。否则,它将捆绑处理器并阻塞事件循环,直到JSON内容完全流化。
在NPM中有很多包可用于此目的。选择最适合你的。
错误处理/安全如果您不确定传递给
使用json对象:
1 | JSON.parse(str); |
json.parse的另一个示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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); }); |
我想提一下,对于全局JSON对象,还有其他的选择。
看看:https://github.com/joyent/node/wiki/modules wiki解析器json
包括
1 2 | var fs = require("fs"); var file = JSON.parse(fs.readFileSync("./PATH/data.json","utf8")); |
有关"fs"库的详细信息,请参阅http://nodejs.org/api/fs.html上的文档。
因为您不知道您的字符串实际上是有效的,所以我首先将它放入一个try catch。另外,由于try catch块没有按节点优化,所以我将把整个功能放到另一个函数中:
1 2 3 4 5 6 7 | function tryParseJson(str) { try { return JSON.parse(str); } catch (ex) { return null; } } |
或"异步样式"
1 2 3 4 5 6 7 8 9 | function tryParseJson(str, callback) { process.nextTick(function () { try { callback(null, JSON.parse(str)); } catch (ex) { callback(ex) } }) } |
分析JSON流?使用
1 2 3 4 5 6 7 8 | 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
这里的每个人都告诉过json.parse,所以我想说点别的。有一个伟大的模块连接许多中间件,使应用程序的开发更容易和更好。其中一个中间件是BodyParser。它解析JSON、HTML表单等,还有一个专门用于JSON解析的中间件noop。
看看上面的链接,它可能对你很有帮助。
1 | JSON.parse("your string"); |
这就是全部。
正如这里提到的其他答案,您可能希望要么需要一个本地JSON文件,您知道它是安全的,并且是存在的,比如配置文件:
1 | var objectFromRequire = require('path/to/my/config.json'); |
或者使用全局JSON对象将字符串值解析为对象:
1 2 | var stringContainingJson = '"json that is obtained from somewhere"'; var objectFromParse = JSON.parse(stringContainingJson); |
注意,当您需要一个文件时,会对该文件的内容进行评估,这会带来安全风险,以防它不是JSON文件而是JS文件。
在这里,我发布了一个演示,您可以在其中看到这两种方法,并在线使用它们(解析示例在app.js文件中-然后单击运行按钮并在终端中看到结果):http://staging1.codefresh.io/labs/api/env/json-parse-example
您可以修改代码并查看其影响…
使用json配置node.js?读这个,你的配置技能超过9000…
Note: People claiming that data = require('./data.json'); is a
security risk and downvoting people's answers with zealous zeal: You're exactly and completely wrong.
Try placing non-JSON in that file... Node will give you an error, exactly like it would if you did the same thing with the much slower and harder to code manual file read and then subsequent JSON.parse(). Please stop spreading misinformation; you're hurting the world, not helping. Node was designed to allow this; it is not a security risk!
正确的应用程序有三层以上的配置:
大多数开发人员将他们的服务器和应用程序配置视为可以更改。它不能。你可以从更高的层上相互层叠变化,但是你正在修改基本需求。有些东西需要存在!使您的配置看起来是不可变的,因为其中一些基本上是,就像您的源代码一样。
如果你看不到很多东西在启动后都不会改变,就会产生反模式,比如在配置加载中乱扔try/catch块,假装你没有正确的设置应用程序就可以继续。不能。如果可以,它属于社区/用户配置层,而不是服务器/应用程序配置层。你只是做错了。当应用程序完成它的引导时,可选的东西应该放在上面。
别把头撞在墙上了:你的配置应该非常简单。
看看使用一个简单的json配置文件和简单的app.js文件来设置像协议不可知和数据源不可知的服务框架这样复杂的东西有多简单…
容器配置JS…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | { "service": { "type" :"http", "name" :"login", "port" : 8085 }, "data": { "type" :"mysql", "host" :"localhost", "user" :"notRoot", "pass" :"oober1337", "name" :"connect" } } |
索引…(驱动一切的发动机)
1 2 3 4 5 6 7 8 9 | 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); }); |
应用程序…(支持协议不可知和数据源不可知服务的代码)
1 2 3 | module.exports = function(request, response){ response.end('Responding to: ' + request.url); } |
使用这种模式,您现在可以在启动的应用程序上加载社区和用户配置的内容,dev ops准备将您的工作推送到容器中并对其进行缩放。你读的是多手语。userland是孤立的。现在,您可以将所使用的服务协议、所使用的数据库类型分离开来,只需专注于编写好的代码。
因为您使用的是层,所以您可以在任何时候(分层配置对象)都依赖于单一的事实源,并避免在每一步都进行错误检查,担心"噢,废话,如果没有正确的配置,我该如何使此工作?""?".
我的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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); }); |
只想完成答案(我挣扎了一会儿),想展示如何访问JSON信息,这个例子展示了如何访问JSON数组:
1 2 3 4 5 6 7 8 | var request = require('request'); request('https://server/run?oper=get_groups_joined_by_user_id&user_id=5111298845048832', function (error, response, body) { if (!error && response.statusCode == 200) { var jsonArr = JSON.parse(body); console.log(jsonArr); console.log("group id:" + jsonArr[0].id); } }) |
只是为了让事情尽可能复杂,尽可能多的带进包裹…
1 2 3 4 5 | const fs = require('fs'); const bluebird = require('bluebird'); const _ = require('lodash'); const readTextFile = _.partial(bluebird.promisify(fs.readFile), _, {encoding:'utf8',flag:'r'}); const readJsonFile = filename => readTextFile(filename).then(JSON.parse); |
这样可以做到:
1 2 | var dataPromise = readJsonFile("foo.json"); dataPromise.then(console.log); |
或者如果您正在使用异步/等待:
1 | let data = await readJsonFile("foo.json"); |
与仅使用
parse不能确保所分析的JSON字符串的安全性。您应该查看类似于JSON安全解析的库或类似的库。
从json safe parse npm页面:
JSON.parse is great, but it has one serious flaw in the context of JavaScript: it allows you to override inherited properties. This can become an issue if you are parsing JSON from an untrusted source (eg: a user), and calling functions on it you would expect to exist.
利用Lodash的尝试函数返回一个错误对象,您可以使用ISerRor函数处理该对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // Returns an error object on failure function parseJSON(jsonString) { return _.attempt(JSON.parse.bind(null, jsonString)); } // Example Usage var goodJson = '{"id":123}'; var badJson = '{id:123}'; var goodResult = parseJSON(goodJson); var badResult = parseJSON(badJson); if (_.isError(goodResult)) { console.log('goodResult: handle error'); } else { console.log('goodResult: continue processing'); } // > goodResult: continue processing if (_.isError(badResult)) { console.log('badResult: handle error'); } else { console.log('badResult: continue processing'); } // > badResult: handle error |
始终确保在try catch块中使用json.parse作为节点。如果JSON中有一些损坏的数据,则始终会引发意外错误,因此请使用此代码而不是简单的json.parse。
1 2 3 4 5 6 | try{ JSON.parse(data) } catch(e){ throw new Error("data is corrupted") } |
如果要在JSON中添加一些注释并允许使用后面的逗号,可以使用以下实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 | var fs = require('fs'); var data = parseJsData('./message.json'); console.log('[INFO] data:', data); function parseJsData(filename) { var json = fs.readFileSync(filename, 'utf8') .replace(/\s*\/\/.+/g, '') .replace(/,(\s*\})/g, '}') ; return JSON.parse(json); } |
注意,如果您的JSON中有类似于
如果JSON源文件非常大,那么可能需要考虑使用node.js 8.0通过本机异步/等待方法进行异步路由,如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | const fs = require('fs') const fsReadFile = (fileName) => { fileName = `${__dirname}/${fileName}` return new Promise((resolve, reject) => { fs.readFile(fileName, 'utf8', (error, data) => { if (!error && data) { resolve(data) } else { reject(error); } }); }) } async function parseJSON(fileName) { try { return JSON.parse(await fsReadFile(fileName)); } catch (err) { return { Error: `Something has gone wrong: ${err}` }; } } parseJSON('veryBigFile.json') .then(res => console.log(res)) .catch(err => console.log(err)) |
我额外使用fs。我很喜欢它,因为-虽然它支持回调-它也支持承诺。所以它只让我以一种更易读的方式编写代码:
1 2 3 4 5 6 7 | const fs = require('fs-extra'); fs.readJson("path/to/foo.json").then(obj => { //Do dome stuff with obj }) .catch(err => { console.error(err); }); |
它也有许多有用的方法,这些方法与标准的
NOTE: You can still use the native Node.js methods. They are promisified and copied over to fs-extra. See notes on
fs.read() &fs.write()
所以基本上都是优点。我希望其他人能发现这一点。
如上所述,我们可以使用
这样使用是安全的
1 2 3 4 5 6 | let parsedObj = {} try { parsedObj = JSON.parse(data); } catch(e) { console.log("Cannot parse because data is not is proper json format") } |
您可以使用json.parse()(这是一个内置函数,可能会迫使您用try catch语句包装它)。
或者使用一些JSON解析NPM库,比如JSON解析或
用这个来保证安全
1 | var data = JSON.parse(Buffer.concat(arr).toString()); |
nodejs是一个基于javascript的服务器,所以您可以用纯javascript来实现这一点…
假设你在nodejs中有这个json…
1 2 | var details = '{"name":"Alireza Dezfoolian","netWorth":"$0" }'; var obj = JSON.parse(details); |
您可以通过上面的操作获得JSON的解析版本…
使用
以下是一些例子:
1 2 3 4 5 6 | var jsonStr = '{"result":true,"count":42}'; obj = JSON.parse(jsonStr); console.log(obj.count); //expected output: 42 console.log(obj.result); // expected output: true |
不需要进一步的模块。只使用
很简单,您可以使用
这必须对我大喊大叫:它只对
如果文件结尾不同,则不起作用!
1 2 3 4 5 6 7 8 9 10 11 12 13 | var fs = require('fs'); fs.readFile('ashish.json',{encoding:'utf8'},function(data,err) { if(err) throw err; else { console.log(data.toString()); } }) |