Home > Blockchain >  fs.readFileSync gives duplicated results when reading JSON files in node.js
fs.readFileSync gives duplicated results when reading JSON files in node.js

Time:01-06

I got two JSON files that I'm processing:

  • sorted/apr-total2.json
  • sorted/may-total2.json

There are files for other months of the year, but for debugging purposes I'm focusing on these two because they are causing the problem.

They contain simple data in the following format:

[
["John", 1403],
["Peter", 1159],
...
]

However, John is available only in sorted/apr-total2.json file and not in sorted/may-total2.json.

My code is the following:

let months = ["apr", "may"];
let dataToSort = {};

function getDataFromJSONFile(month) {
  let jsonData = fs.readFileSync(`sorted/${month}-total2.json`);
  let convertedData = JSON.parse(jsonData);
  return convertedData;
}

function arrayToObject(data) {
  data.forEach((user) => {
    dataToSort[user[0].toString()] = user[1];
  });
  return dataToSort;
}

for (let i in months) {
  let currentMonth = months[i];
  console.log("Current month is "   currentMonth);
  let getDataForMonth = getDataFromJSONFile(currentMonth);
  let convertedMonth = arrayToObject(getDataForMonth);
  if (convertedMonth.hasOwnProperty("John") == true) {
    console.log(true);
  }
}

My output is the following:

Current month is apr
true
Current month is may
true

This isn't correct, since user John isn't available in sorted/may-total2.json. So why is this happening? It seems that the object convertedMonth is causing the issue.

If I add the following code at the end of the for loop and delete the ConvertedMonth object properties:

for (let item in convertedMonth) {
  delete convertedMonth[item];
}

It works as intended:

Current month is apr
true
Current month is may

I want to know why this object is causing the issue, because I reused the same code in another place of my project.

CodePudding user response:

Your arrayToObject function uses a single global dataToSort, so any entries will be accumulated and overwritten there. See:

> let dataToSort = {};
> function arrayToObject(data) {
...   data.forEach((user) => {
...     dataToSort[user[0].toString()] = user[1];
...   });
...   return dataToSort;
... }
> arrayToObject([["foo", 123]])
{ foo: 123 }
> arrayToObject([["foo", 456], ["bar", 567]])
{ foo: 456, bar: 567 }

Your program simplifies to something like

let months = ["apr", "may"];

for (let currentMonth of months) {
    console.log("Current month is "   currentMonth);
    let jsonData = JSON.parse(fs.readFileSync(`sorted/${month}-total2.json`));
    let convertedMonth = Object.fromEntries(jsonData);
    if (convertedMonth["John"]) {
        console.log(true);
    }
}

which

  • uses for..of for correct and simpler iteration over the months
  • uses Object.fromEntries to convert an array of 2-arrays into a plain object (which is what your arrayToObject did)
  • Related