首页 文章

如何使用Node.js解析JSON?

提问于
浏览
885

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

30 回答

  • 9

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

    var objectFromRequire = require('path/to/my/config.json');
    

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

    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

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

  • 1

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

    JSON 对象is part of the ECMAScript 5 specification的定义 . node.js Build 在谷歌Chrome的V8引擎上,符合ECMA标准 . 因此,node.js还有一个全局对象JSON[docs] .

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

  • 632

    你可以require .json文件 .

    var parsedJSON = require('./file-name');
    

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

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

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

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

    请注意 requiresynchronous 并且只读取文件 once ,以下调用从缓存返回结果

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

  • 28

    You can use JSON.parse() .

    您应该能够在任何兼容_1611873的JavaScript实现上使用 JSON 对象 . 构建Node.js的V8就是其中之一 .


    解析包含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吗?再想想!

    You can sometimes use require

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

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

    注意:如果您使用JSON文件存储敏感信息(例如密码),那么这是错误的方法 . 了解Heroku如何做到这一点:https://devcenter.heroku.com/articles/config-vars#setting-up-config-vars-for-a-deployed-application . 了解您的平台如何做到这一点,并使用process.env从代码中检索配置变量 .

    • require 是同步的 . 如果你有一个非常大的JSON文件,它会阻塞你的事件循环 . 你真的需要使用 JSON.parsefs.readFile .

    • require 将读取文件 only once . 对同一文件的 require 的后续调用将返回缓存副本 . 如果您想要阅读不断更新的 .json 文件,这不是一个好主意 . 你可以使用a hack . 但在这一点上,简单地使用 fs 更容易 .

    • 如果您的文件没有 .json 扩展名, require 将不会将该文件的内容视为JSON .

    Seriously! Use 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内容完全流式传输 .

    这有plenty of packages available in NPM . 选择最适合您的方式 .


    错误处理/安全性

    如果您不确定传递给 JSON.parse() 的内容是否为valid JSON,请确保将 JSON.parse() 的调用封闭在 try/catch 块中 . 用户提供的JSON字符串可能会导致应用程序崩溃,甚至可能导致安全漏洞 . 如果解析外部提供的JSON,请确保完成错误处理 .

  • 7

    使用JSON object

    JSON.parse(str);
    
  • 295

    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);
    });
    
  • 32

    我想提一下全局JSON对象的替代品 . JSON.parseJSON.stringify 都是同步的,因此如果要处理大对象,可能需要查看一些异步JSON模块 .

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

  • -1

    包括 node-fs 库 .

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

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

  • 5

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

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

    或“异步风格”

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

    解析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

  • 2
    JSON.parse("your string");
    

    就这样 .

  • 33

    这里的每个人都讲过JSON.parse,所以我想说点别的 . 有一个很棒的模块Connect有很多中间件可以让应用程序的开发变得更容易和更好 . 其中一个中间件是bodyParser . 它解析JSON,html表单等 . 还有一个特定的JSON解析中间件noop .

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

  • 79

    我的解决方案

    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

    只是为了让它尽可能复杂,并尽可能多地引入包...

    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);
    

    这可以让你做到:

    var dataPromise = readJsonFile("foo.json");
    dataPromise.then(console.log);
    

    或者,如果您使用async / await:

    let data = await readJsonFile("foo.json");
    

    与仅使用 readFileSync 相比,优点是您的节点服务器可以在从磁盘读取文件时处理其他请求 .

  • 1

    只想完成答案(因为我挣扎了一段时间),想要展示如何访问json信息,这个例子显示访问Json数组:

    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);
      }
    })
    
  • 4

    Using JSON for your configuration with Node.js? Read this and get your configuration skills over 9000...

    注意:声称data = require('./ data.json')的人;是一种安全风险,并以热心的热情贬低人们的答案:你是完全错误的 . 尝试在该文件中放置非JSON ... Node会给你一个错误,就像你用同样的东西做同样的事情,用更慢更难编码的手动文件读取然后再用JSON.parse() . 请停止传播错误信息;你在伤害世界,没有帮助 . 节点的设计允许这样做;这不是安全风险!

    正确的应用程序有3: layers 的配置:

    • 服务器/容器配置

    • 应用程序配置

    • (可选)租户/社区/组织配置

    • 用户配置

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

    没有看到很多你的东西在启动后不会改变导致反模式,比如乱丢你的配置加载try / catch块,并且假装你可以继续 without 你正确设置的应用程序 . 你可以't. If you can, that belongs in the community/user config layer, not the server/app config layer. You'只是做错了 . 当应用程序完成引导程序时,可选的东西应该在顶部分层 .

    不要把头撞在墙上:你的配置应该是 ultra simple .

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

    container-config.js...

    {
        "service": {
            "type"  : "http",
            "name"  : "login",
            "port"  : 8085
        },
        "data": {
            "type"  : "mysql",
            "host"  : "localhost",
            "user"  : "notRoot",
            "pass"  : "oober1337",
            "name"  : "connect"
        }
    }
    

    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); });
    

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

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

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

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

  • 3

    如果您想在JSON中添加一些注释并允许使用尾随逗号,您可能需要在下面的实现中使用:

    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中有 "abc": "foo // bar" 之类的内容,它可能无法正常工作 . 所以YMMV .

  • 0

    JSON.parse不会确保您正在解析的json字符串的安全性 . 您应该查看像json-safe-parse这样的库或类似的库 .

    从json-safe-parse npm页面:

    JSON.parse很棒,但它在JavaScript的上下文中有一个严重的缺陷:它允许您覆盖继承的属性 . 如果您从不受信任的源(例如:用户)解析JSON,并调用您希望存在的函数,这可能会成为一个问题 .

  • 5

    利用Lodash的尝试函数返回一个错误对象,您可以使用isError函数处理该错误对象 .

    // 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
    
  • 0

    始终确保在 try catch 块中使用JSON.parse,因为如果json中有一些损坏的数据,节点总是会抛出一个意外错误,所以请使用此代码而不是简单的JSON.Parse

    try{
         JSON.parse(data)
    }
    catch(e){
       throw new Error("data is corrupted")
      }
    
  • -1
    var array={
        Action: 'Login',
        ErrorCode: 3,
        Detail: 'Your account not found.'
    };
    var http=require('http'),
        PORT=8789,
        server=function(req,res){
            res.writeHead(200,{'Content-Type':'application/json'});
    
            // JSON
            res.end(JSON.stringify(array));
        }
    
    http.createServer(server).listen(PORT);
    console.log('Server started.');
    
  • 1018

    如果JSON源文件非常大,可能需要通过Native.js 8.0的native async / await方法考虑异步路由,如下所示

    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))
    
  • 6

    这不得不对我大喊:它只适用于 .json 文件 .

    如果文件结尾不同,这不起作用!

  • 0

    您可以使用JSON.parse()(这是一个内置函数,可能会强制您使用try-catch语句包装它) .

    或者使用一些JSON解析npm库,类似json-parse-or

  • 0

    使用它是为了安全起见

    var data = JSON.parse(Buffer.concat(arr).toString());

  • 2

    无需其他模块 .
    只是用
    var parsedObj = JSON.parse(yourObj);
    我认为这方面没有任何安全问题

  • 4

    我用fs-extra . 我非常喜欢它 - 因为它支持回调 - 它也支持Promises . 所以它只是让我以更易读的方式编写我的代码:

    const fs = require('fs-extra');
    fs.readJson("path/to/foo.json").then(obj => {
        //Do dome stuff with obj
    })
    .catch(err => {
        console.error(err);
    });
    

    它还有许多有用的方法,它们不与标准 fs 模块一起提供,并且最重要的是,它还将方法与本机 fs 模块连接起来并对它们进行预定 .

    注意:您仍然可以使用本机Node.js方法 . 他们被宣传并复制到fs-extra . 请参阅有关fs.read()和fs.write()的说明

    所以它基本上都是优点 . 我希望其他人觉得这很有用 .

  • 4

    这很简单,您可以使用 JSON.stringify(json_obj) 将JSON转换为字符串,并使用 JSON.parse("your json string") 将字符串转换为JSON .

  • 0

    使用 JSON.parse(str); . 阅读更多here .

    这里有些例子:

    var jsonStr = '{"result":true, "count":42}';
    
    obj = JSON.parse(jsonStr);
    
    console.log(obj.count);    //expected output: 42
    console.log(obj.result);   // expected output: true
    
  • 8
    var fs = require('fs');
    
    fs.readFile('ashish.json',{encoding:'utf8'},function(data,err) {
    
       if(err) 
          throw err;
    
       else {
    
       console.log(data.toString());
    
     }
    })
    

相关问题