Search code examples
javascriptnode.jsjsonobjectnode.js-fs

fs.writeFile adds extra brackets to json of key=>values object in node.js


I'm trying to update one JSON file in a for loop called asynchronously. Each time I update the whole file, with 1 object.

This is my very complex code after half a day of research. (I know it's too complex, but I wanted to show what I've tried so far)

    async function saveJsonFile(data, fileName = 'myFile') {
      try {
        const jsonData = JSON.stringify(data);

        // clear cache
        delete require.cache[require.resolve(`./${fileName}.json`)];

        // ensure the file exists
        await fs.readFile(`${fileName}.json`, 'utf8', (err) => {
          if (err) {} 
          else {
            // clear the content of the file
            fs.writeFile(`${fileName}.json`, "", "utf8", (err) => {
              if (err) {} 
              else {

                // save the json << THIS IS WHERE I STARTED WITH
                fs.writeFile(`${fileName}.json`, jsonData, 'utf8', (err) => {
                  if (err) {
                  }
                });                
                
                // try saving again
                fs.writeFile(`${fileName}.json`, jsonData, 'utf8', (err) => {
                  if (err) {
                  }
                });
              }
            });
          }
        });
      } 
    }

Called from another async func:

async function runTrading()
{
  try {
    for (let i = 1; i <= data.length; i++) {
    ...
    lastBuyPrice[symbol] = currentPrice;
    await saveJsonFile(lastBuyPrice);         

This is what I get (different loops, tries, versions, etc.) Notice the 2 brackets at the end of each line, or in the middle. In the log it looks OK before saving!

{"prod1":32154.22}} or {"prod1":32154.22,"prod2":0,"prod3":0}32}}


Solution

  • The original code had multiple issues causing JSON corruption and inconsistent file writes:

    • Mixed async patterns – It used fs.readFile with a callback inside an async function, making await ineffective.
    • Race conditions – Multiple fs.writeFile calls could overlap, leading to incomplete or corrupted JSON.
    • Non-atomic writes – Clearing and rewriting the file multiple times increased the risk of partial writes.
    • Lack of proper error handling – Errors weren't properly caught, making debugging harder.
    const fs = require('fs').promises;
    const path = require('path');
    
    async function saveJsonFile(data, fileName = 'myFile') {
        try {
            const filePath = path.join(__dirname, `${fileName}.json`);
            const jsonData = JSON.stringify(data, null, 2);
    
            // write file
            await fs.writeFile(filePath, jsonData, 'utf8');
        } catch (err) {
            console.error("Error al guardar el archivo JSON:", err);
        }
    }
    
    async function runTrading() {
        try {
            for (let i = 0; i < data.length; i++) {
                let symbol = "prod" + (i + 1);
                let currentPrice = Math.random() * 1000; // price simulation
    
                lastBuyPrice[symbol] = currentPrice;
                await saveJsonFile(lastBuyPrice);
            }
        } catch (err) {
            console.error("Error en runTrading:", err);
        }
    }