1

I need to add a song to a .json file. The json is an object, with inside objects.

{
  "Song title 1": {
    "title": "Song title 1",
    "author": "Song author 1",
    "date": "1894"
  },
  "Song title 2": {
    "title": "Song title 2",
    "author": "Song author 2",
    "date": "2000"
  },
  "title": {
    "title": "yyyy",
    "author": "",
    "date": "ggggg"
  }
}

In the json above was added by running the function saveSongs("yyyy", "", "ggggg")

export const saveSongs = async (title, author, date) => {
  const songs = JSON.parse(await fs.readFileSync(
    'songs.json', 'utf-8'
  ));

  const newSong = {
    title: {
      "title": title,
      "author": author,
      "date": date
    }
  }

  const updatedBookList = Object.assign(song, newSong)
  console.log(updatedSongList);

  fs.writeFileSync("songs.json", JSON.stringify(updatedSongList))

};

The problem is that the key of the object needs to be the same as the title. So instead of

"title": {
        "title": "yyyy",
        "author": "",
        "date": "ggggg"
      }

it should save

"yyyy": {
        "title": "yyyy",
        "author": "",
        "date": "ggggg"
      }

In order to fix that it originall was as a string:

  const newSong = {
    "title": {
      "title": title,
      "author": author,
      "date": date
    }
  }

so I removed the string quotes... but stil the same.

How can I fix that?

Pikk
  • 2,343
  • 6
  • 25
  • 41

2 Answers2

6

To dynamically set the title value as the key, use the [title]: ... notation:

const newSong = {
  [title]: {
    "title": title,
    "author": author,
    "date": date
  }
}

Also, do not use await fs.readFileSync because readFileSync returns the value. Instead, use await fs.promises.readFile which uses promises:

export const saveSongs = async (title, author, date) => {
  const songs = JSON.parse(await fs.promises.readFile(
    'songs.json', 'utf-8'
  ));

  const newSong = {
    [title]: {
      "title": title,
      "author": author,
      "date": date
    }
  }

  const updatedBookList = Object.assign(song, newSong)
  console.log(updatedSongList);

  await fs.promises.writeFile("songs.json", JSON.stringify(updatedSongList))

};
Ionică Bizău
  • 109,027
  • 88
  • 289
  • 474
  • 1
    perfect answer. for the JS vocabulary nerds among us, this is called a [property accessor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors). – Zev Averbach Mar 02 '22 at 08:43
  • Note on the `fs.readFileSync` comment. You can import `fs/promises` instead of `fs` to directly import promise functions, then `await fs.readFile()`, although it does remove synchronous functions (`fs.readFileSync()` is no longer included). It could be useful if you only use asynchronous functions. – Arkin Solomon Mar 02 '22 at 08:51
0

Use the following code :

const newSong = { [title]: { "title": title, "author": author, "date": date } }