如何在没有密钥的情况下访问JSON文件的内容?

时间:2018-06-13 03:07:44

标签: json node.js express

基本上,我通过Node.js和Express(我是初学者)设置一个Web服务器,通过读取JSON文件来检索数据。 例如,这是我的data.json文件:

[{
        "color": "black",
        "category": "hue",
        "type": "primary"
    },
    {
        "color": "red",
        "category": "hue",
        "type": "primary"
    }
]

我试图通过实现此代码来检索所有颜色,以便在localhost上显示:

router.get('/colors', function (req, res) {
    fs.readFile(__dirname + '/data.json', 'utf8', function (err, data) {
        data = JSON.parse(data);
        res.json(data); //this displays all of the contents of data.json
    })
});

router.get('/colors:name', function (req, res) {
    fs.readFile(__dirname + '/data.json', 'utf8', function (err, data) {
        data = JSON.parse(data);
        for (var i = 0; i < data.length; i++) {
            res.json(data[i][1]); //trying to display the values of color
        }
    })
});

我该怎么做?

6 个答案:

答案 0 :(得分:2)

一旦你把它分解成更小的问题,你想要做的事情实际上非常简单。这是打破它的一种方法:

  1. 将您的JSON数据加载到内存中以供API使用。
  2. 定义一个API路由,该路由仅从JSON数据中提取颜色并将其作为JSON发送到客户端。
  3. var data = [];
    try {
        data = JSON.parse(fs.readFileSync('/path/to/json'));
    } catch (e) {
        // Handle JSON parse error or file not exists error etc
        data = [{
                "color": "black",
                "category": "hue",
                "type": "primary"
            },
            {
                "color": "red",
                "category": "hue",
                "type": "primary"
            }
        ]
    }
    
    router.get('/colors', function (req, res, next) {
        var colors = data.map(function (item) {
            return item.color
        }); // This will look look like: ["black","red"]
        res.json(colors); // Send your array as a JSON array to the client calling this API
    })
    

    此方法的一些改进:

    1. 启动应用程序时,文件只能同步读取一次,并且数据会缓存在内存中以备将来使用。
    2. 使用Array.prototype.map Docs从对象中提取颜色数组。
    3. 注意:

      您可以根据需要构建颜色数组,并将其作为JSON发送到该结构中。

      示例:

      var colors = data.map(function(item){return {color:item.color};}); // [{"color":"black"},{"color":"red"}]
      
      var colors = {colors: data.map(function(item){return item.color;})} // { "colors" : ["black" ,"red"] }
      

      代码中的一些问题:

      1. 您在for循环中使用res.json这是不正确的,因为响应应该只发送一次。理想情况下,您可以通过迭代数据并使用res.json(我在内部猜测JSON.stringify对象并将其作为设置正确的标题后的响应)
      2. 阅读文件是一项昂贵的操作。如果你有能力读一次并将这些数据缓存在内存中,那么效率会很高(假设您的数据不是非常大 - 在这种情况下使用文件存储信息可能效率低下)。

答案 1 :(得分:1)

在快递中,你可以这样做

router.get('/colors/:name', (req, res) => {
  const key = req.params.name
  const content = fs.readFileSync(__dirname + '/data.json', 'utf8')
  const data = JSON.parse(content)
  const values = data.reduce((values, value) => {
    values.push(value[key])
    return values      
  }, [])
  // values => ['black', 'red']
  res.send(values)
});

然后curl http://localhost/colors/color
你可以得到[&#39; black&#39;,&#39; red&#39;]

答案 2 :(得分:0)

您要做的是:

res.json(data[i]['color']);

答案 3 :(得分:0)

如果你真的不想使用json中的键,你可能想要使用Object.values函数。

...
data = JSON.parse(data)
var values = []
for (var i = 0; i < data.length; i++) {
    values.push(Object.values(data[i])[0]) // 0 - color, 1 - category, 2 - type
}
res.json(values) // ["black","red"]
...

答案 4 :(得分:0)

你绝不能在生产中使用fs.readFileSync。任何同步函数都会阻止事件循环,直到执行完成,因此在之后延迟所有内容(如果认为有必要,请谨慎使用)。几天前,我自己遇到了最糟糕的经历,并以一种艰难的方式学到了这一点。

在快递中,您可以使用paramquery定义路线,并将其用于map fs.readFile回调函数内的内容。

/** 
* get color by name
* 
* @param {String} name name of the color
* @return {Array} array of the color data matching param
*/

router.get('/colors/:name', (req, res) => {
    const color = req.params.name

    const filename = __dirname + '/data.json';

    fs.readFile('/etc/passwd', 'utf8', (err, data) => {
        if(err){
            return res.send([]); // handle any error returned by readFile function here
        }

        try{
            data = JSON.parse(data); // parse the JSON string to array

            let filtered = []; // initialise empty array

            if(data.length > 0){ // we got an ARRAY of objects, right? make your check here for the array or else any map, filter, reduce, forEach function will break the app
                filtered = data.filter((obj) => {
                    return obj.color === color; // return the object if the condition is true
                });
            }

            return res.send(filtered); // send the response 

    }
    catch(e){
      return res.send([]); // handle any error returned from JSON.parse function here
    }
  });

});

总而言之,使用fs.readFile异步函数,以便事件循环不会被阻塞。在回调内部解析内容,然后return响应。 return非常重要,否则您最终可能会收到错误:发送后无法设置标题

免责声明以上代码未经测试但应该有效。这只是为了证明这个想法。

答案 5 :(得分:-1)

我认为没有密钥你就无法访问JSON。您可以使用Foreach循环(var name:object){}检查foreach它可能对您有所帮助