fs.readFileSync 在 Node.js 中读取 JSON 文件时会产生重复的结果。

huangapple go评论77阅读模式
英文:

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

问题

The issue you're encountering seems to be related to the reuse of the dataToSort object across different months. When you reuse the same object for both April and May, it accumulates data from both months. To fix this issue, you should initialize the dataToSort object inside the for loop for each month. Here's the corrected code for your understanding:

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

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

function arrayToObject(data) {
  let dataToSort = {}; // Initialize a new object for each month
  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);
  }
}

By initializing dataToSort inside the arrayToObject function for each month, you ensure that the data from previous months doesn't accumulate, and the code should work as intended.

英文:

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.

答案1

得分: 3

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)
英文:

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)

huangapple
  • 本文由 发表于 2023年1月5日 15:27:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75015076.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定