3

I am new to node.js and kind of stuck here. I have a json file keyValue.json which resembles this

[ {
    "key": "key1",
    "value": "value1"
  },   
  {
    "key": "key2",
    "value": "value2"
  } 
]

For a particular key I need to get the value.

function filterValue() {
  const category = {};
  category.filter = "key1" //this is not static value. This changes dynamically
  category.value = //Need to read the keyValue.json file and pick the value for key1 - which is value1
  return category;
}

How can this be achieved in node.js. Thanks for helping out.

Erty Seidohl
  • 4,487
  • 3
  • 33
  • 45
fledgling
  • 991
  • 4
  • 25
  • 48
  • Possible duplicate of [Find object by id in an array of JavaScript objects](https://stackoverflow.com/questions/7364150/find-object-by-id-in-an-array-of-javascript-objects) – CertainPerformance Jan 05 '19 at 01:33
  • It is different from the above in 2 aspects. 1. I am not looking up a static value 2. I want to be able to read from a file – fledgling Jan 05 '19 at 01:58
  • Whether it can change or not doesn't matter, you can still use the method used in the linked question. – CertainPerformance Jan 05 '19 at 01:59
  • The example uses an array. Mine is a file. do I need to read the file into an array to do this? – fledgling Jan 05 '19 at 02:02
  • See [here](https://www.google.com/search?q=how+to+read+json+file+to+object+javascript) eg [this](https://stackoverflow.com/questions/10011011/using-node-js-how-do-i-read-a-json-object-into-server-memory) – CertainPerformance Jan 05 '19 at 02:05

2 Answers2

9

I am assuming that you have your json parsed into a variable. So my example will use this:

const data = [ 
  {
    key: "key1",
    value: "value1"
  },   
  {
    key: "key2",
    value: "value2"
  } 
];

If not, then in node we can just require it as long as it is a static file. But this will be loaded once for the execution span of the app.

const data = require('./file.json');

If it needs to be dynamically read because it is changing for some reason then you need to use fs (always do it async in node).

const fs = require('fs');

fs.readFile('./file.json', 'utf8', function(err, contents) {
    if (err) {
      // we have a problem because the Error object was returned
    } else {
      const data = JSON.parse(contents);
      ... use the data object here ...
    }
});

If you prefer Promises to callbacks:

const fs = require('fs');

// ES7 Version
const getJsonFile = (filePath, encoding = 'utf8') => (
   new Promise((resolve, reject) => {
      fs.readFile(filePath, encoding, (err, contents) => {
          if(err) {
             return reject(err);
          }
          resolve(contents);
      });
   })
     .then(JSON.parse)
);

// ES6 Version
const getJsonFile = function getJsonFile(filePath, encoding = 'utf8') {
   return new Promise(function getJsonFileImpl(resolve, reject) {
      fs.readFile(filePath, encoding, function readFileCallback(err, contents) {
          if(err) {
             return reject(err);
          }
          resolve(contents);
      });
   })
     .then(JSON.parse);
};

Now with either of these you can simply use the Promise

getJsonFile('./file.json').then(function (data) { ... do work });

or if using async

const data = await getJsonFile('./file.json');

So now we would want a composable filter to use with Array's find method. In the latest versions of Node (Carbon and above):

const keyFilter = (key) => (item) => (item.key === key);

If you are node 6 or below lets do this the old way

const keyFilter = function keyFilter(key) {
   return function keyFilterMethod(item) {
      return item.key === key;
   }
};

Now we can use this filter on the array changing out the key we are looking for at any time (because it is composable).

const requestedItem = data.find(keyFilter('key2');

If the key doesn't exist undefined will be returned, otherwise, we have the object.

const requestedValue = requestedItem ? requestedItem.value : null;

This filter can also be used for other searches in the Array such as finding the index

const index = data.findIndex(keyFilter('key2'));

If "key" was allowed to be duplicated in the array, you could grab them all using filter

const items = data.filter(keyFilter('key2'));

To sum it all up we would probably put our areas of concern in different files. So maybe a getJsonFile.js and a keyFilter.js so now put together we would look something like this (calling this file readKeyFromFile):

const getJsonFile = require('./getJsonFile');
const keyFilter = require('./keyFilter');

module.exports = async (filePath, keyName) => {
   const json = await getJsonFile(filePath);
   const item = json.find(keyFilter(keyName));
   return item ? item.value : undefined;
};

and our consumer

const readKeyFromFile = require('./readKeyFromFile');

readKeyFromFile('./file.json', 'key2').then((value) => {
   console.log(value);
};

There are so many combinations of how you can do this once these fundamentals are understood. So have fun with them. :)

Victoria French
  • 756
  • 5
  • 10
  • in the second to last code snippet ```const json = getJsonFile(filePath);``` should be ```const json = await getJsonFile(filePath);```. Excellent answer though. – Bill Christo Feb 15 '23 at 22:53
0

If you are having json object named keyValue. first import it and named it as keyValue, then try this,

`function filterValue(req, res, next) {
   keyValue
      .find({ key: "key1" })
      .exec()
      .then(result= > {
         return result.value
      })  
}`
Dinusha Naveen
  • 172
  • 1
  • 2
  • 14