Why does it add backslashes in the saved file?

Viewed 236

I have some code which should save a word with the other words in the .json file already and it KINDA does the job, it reads the file(fs.readFileSync) as a const and when saving with fs.WriteFileSync it just puts random 's in the text like this enter image description here

I don't know why it does it but it's really annoying (readBl is a function to read it and save it as a variable just so when I want to I can get it to read it with a command, I know I could do it in other ways but IDC) My code :

if(msg.content.startsWith('-addconf '))
  {
    var newword = msg.content.slice(9);

    if(blacklisted.includes(newword))
      return msg.channel.sendMessage("This word has already been blacklisted.")

    let rawdata = fs.readFileSync('blacklist.json');
    let rawRead = JSON.parse(rawdata);

    const str = JSON.stringify(rawRead);

    const str1 = str.replace('}', '');
    const str2 = str1.replace('{"blacklist":', '');
    //const str3 = str2.replace('""', '');

    let balance = {
    blacklist: str2 + newword
    };

    let data = JSON.stringify(balance);
    fs.writeFileSync('blacklist.json', data);

    readBl();
    msg.channel.sendMessage("Added a blacklisted word, test it out.")
}
2 Answers

A JSON value (like the keys) is enclosed in double quotes.

{ "someKey": "someValue" } 

So, how do you write a value that has quotes in it, like some"Value"With"Quotes"In"It? And you could have much much worse here...

(and more importantly, how does a JSON parser should read back such a value?

Is the value some? Is this a syntax error?

In JSON, like in many other contexts where you need to have delimiters, we need to have a way to tell that the quote " is not the syntax element to end the value, but some character that is part of the value.

The solution: escaping

So we do what is called "escaping" the character. In JSON (and in other languages), the escaping is done by prefixing with a backslash \.

And... since backslash is now a special character as well, that is used for escaping another character, you have the same problem again: how to represent a actual backslash in the value itself?

Simple, same solution: you escape the backslash itself.

So, when saving a JSON string value:

  • quotes " become \";
  • backslashes \ become \\.

How to read that back?

Any functioning JSON reader will read that properly, it's the correct way to serialize those characters, so you don't have any issue here!

I want to make a blocklist so if you type "-addconf " it will save that word to a file and when the bot starts(or you add a new word) it saves the blacklist as a var so I can check later if the message's content actually have some of the blacklisted words in them. How can I achieve that?

You achieve that by storing the word in an array. You only need to read the file once when the code starts up and then you just add to the array and write it to the file.

// At the beginning
// blacklist.json needs to contain {"blacklist": []}
let {blacklist} = JSON.parse(fs.readFileSync('blacklist.json'));

// Wherever...
if(msg.content.startsWith('-addconf '))
  {
    var newword = msg.content.slice(9);

    if(blacklist.includes(newword)) {
      return msg.channel.sendMessage("This word has already been blacklisted.")
    }

    blacklist.push(newword);
    fs.writeFileSync('blacklist.json', JSON.stringify({blacklist}));

    msg.channel.sendMessage("Added a blacklisted word, test it out.")
}

You could even just store the array directly in the file, there is no need to use an object with a blacklist property (unless you want to store additional data.


The reason you ended up with so many backslashes is that your string manipulation probably didn't quite work and so you ended up with garbled text. There is no need for that if you structure your data properly.

Related