0

I need to store an array of URLs associated with number in json file. This is what I got so far:

json[message.guild.id] = {
  songs: []
};
fs.readFile("./settings.json", "utf8", (err, data) => {
  if (err) {
    throw err;
  } else {
    json[message.guild.id] = JSON.parse(data);
  }
});
json[message.guild.id].songs.push(url); // adding a new URL
fs.writeFile("./settings.json", JSON.stringify(json, null, 4), err => {
  if (err) throw err;
});

And this does work, but if I try to save next URL it just overrides the existing one. What is wrong and how I can remove one of the saved URLs?

AnB
  • 119
  • 3
  • 10
  • You are `writing` over the file, that's why. What you want to do is to `append` to it. check this out : https://stackoverflow.com/a/11267583/6212957 – Feelsbadman Jan 05 '19 at 19:19
  • Possible duplicate of [How to append to a file in Node?](https://stackoverflow.com/questions/3459476/how-to-append-to-a-file-in-node) – Feelsbadman Jan 05 '19 at 19:20
  • It's not really clear what you are saving. It might help if you showed an example of the `settings.json` – Mark Jan 05 '19 at 19:31
  • Example: `{ "498208636234104846": { "songs": [ "https://www.youtube.com/watch?v=S81bLqpstUE" ] } }` – AnB Jan 05 '19 at 19:34

2 Answers2

1

Update 2

My first attempt overlooked the JSON issue, which I've left for posterity but you should not do because it will create an incorrect JSON object here.

However, I'm curious how you're kicking off this script. If it's the same block as you provided, you might be resetting the array for the message.guild.id every time. You could try protecting against it with something like this:

if(!json.hasOwnProperty[message.guild.id]){
    json[message.guild.id] = {};
} else if (!json[message.guild.id].hasOwnProperty('songs')){
    json[message.guild.id].songs = [];
}

Again this is just an assumption since we don't see the implementation.

Update fixed typos from paste

You need to add an options object to the writeFile method and set the flag key to 'a'. This tells writeFile to write in append mode. Documentation here and here.

json[message.guild.id] = {
  songs: []
};
fs.readFile("./settings.json", (err, data) => {
  if (err) {
    throw err;
  } else {
    json[message.guild.id] = JSON.parse(data);
  }
});
json[message.guild.id].songs.push(url); // adding a new URL
fs.writeFile("./settings.json", {encoding:"utf8", flag:'a'}, JSON.stringify(json, null, 4), err => {
  if (err) throw err;
});
GenericUser
  • 3,003
  • 1
  • 11
  • 17
  • 1
    How does appending to a JSON file work? Won't this create malformed JSON? – Mark Jan 05 '19 at 19:27
  • You're absolutely correct. I was focusing on correcting the overwrite instead of the data format. – GenericUser Jan 05 '19 at 19:30
  • @Joe I still can't understand that, I want the structure of this file to be like: `{ "498208636234104846": { "songs": [ "https://www.youtube.com/watch?v=S81bLqpstUE", "https://www.youtube.com/watch?v=5lJhX6PGmMo" ] }, "457965143612194829": { "songs": [ "https://www.youtube.com/watch?v=2YeDOa2XoeF", "https://www.youtube.com/watch?v=cPOvNhET5gI" ] } }` This script is fired up when user executes a command to add a song URL for a given guild ID. I hope you can understand me. – AnB Jan 05 '19 at 21:01
0

You are using callback functions, so you can't use it like that

json[message.guild.id] = {
  songs: []
};
fs.readFile("./settings.json", "utf8", (err, data) => {
  if (err) {
    throw err;
  } else {
    json[message.guild.id] = JSON.parse(data);
    json[message.guild.id].songs.push(url); // adding a new URL
    fs.writeFile("./settings.json", JSON.stringify(json, null, 4), err => {
      if (err) throw err;
    });
  }
});

This should work however it seems to not make sense.

Take a look at async functions, callbacks and promises. Specially how callback works, your code has to be executed inside each function

Pedro Silva
  • 2,655
  • 1
  • 15
  • 24
  • OP mentioned `if I try to save next URL it just overrides the existing one` - meaning that it's removing the existing content. So shouldn't he use the `appendFile` function instead of `writeFile`? – Feelsbadman Jan 05 '19 at 19:22
  • Yes, he should or use a flag the @joe answer stated. however the question has a problem with the callbacks – Pedro Silva Jan 05 '19 at 19:24