2

So I'm a beginner to js and I have a table of users in a json file and I'm making an account delete feature. I have a find set up to find the user and it works fine but I can't figure out how to make it delete the user from the file, any help would be appreciated!

Json:

{
    "users": [
        {
            "name": "ImBattleDash",
            "Id": "780748c5d4504446bbba3114ce48f6e9",
            "discordId": "471621420162744342",
            "dateAdded": 1548295371
        }
    ]
}

JS:

    function findJson() {
    fs.readFile('./linkedusers.json', 'utf-8', function (err, data) {
        if (err) message.channel.send('Invalid Code.')

        var arrayOfObjects = JSON.parse(data)
        let findEntry = arrayOfObjects.users.find(entry => entry.discordId == myCode)

        let linkEmbed = new Discord.RichEmbed()
        .setTitle('Account unlinked!')
        .setDescription('Link your account by friending "BattleDash Bot" on Fortnite and then input the code you get messaged by typing "!link <code>"!')
        .setColor('#a900ff');

        message.channel.send({embed: linkEmbed});

    })
}

EDIT: Not sure if it's an array or a table I don't know a lot about json

  • 1
    You can just use `filter`. It uses the inverse logic/predicate as `find` and would result in an array that does not contain the specified user. How you persist changes to the file is a different problem/question. – sellmeadog Jan 24 '19 at 17:57

3 Answers3

0

You need to use:

  • Array#find to find a given user by some given criteria.
  • Array#indexOf to get the index of the found user in users
  • Array#splice to drop one element starting from the index given by Array#indexOf:

const input = {
    "users": [
        {
            "name": "ImBattleDash",
            "Id": "780748c5d4504446bbba3114ce48f6e9",
            "discordId": "471621420162744342",
            "dateAdded": 1548295371
        }
    ]
}

const removeUser = (criteria, users) =>
   users.splice (users.indexOf (users.find (criteria)), 1)
   
   
removeUser (
   ({ Id, discordId }) =>
       Id == '780748c5d4504446bbba3114ce48f6e9' 
       && discordId == '471621420162744342',
     input.users
)

// Output: 0 <-- User has been removed!
console.log(input.users.length)

About persisting the change, it's just about calling JSON.stringify (input) and then just write the contents to the desired output file. See this other Q&A: Writing files in Node.js

Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
  • for const input what do I put since the array is in a json file not in the js file? Sorry –  Jan 24 '19 at 17:55
  • @BattleDash But, do you want to physically drop users from the JSON file? I mean, you want to write the whole file? – Matías Fidemraizer Jan 24 '19 at 17:56
  • Yes I basically have two files, users.json and linkedusers.json, users.json is for unverified users (not linked) and linkedusers.json has users IDs that are linked to their Discord IDs. I'm making the unlink command which would completely delete them from linkedusers.json –  Jan 24 '19 at 17:58
  • @BattleDash Once you've removed the user, you just need to persist the file using `fs.writeFile` in Node. – Matías Fidemraizer Jan 24 '19 at 17:59
  • Yeah In the link command I do that with `fs.writeFile('./linkedusers.json', JSON.stringify(arrayOfObjects, null, 4)`. –  Jan 24 '19 at 18:00
  • @BattleDash I've updated my answer with this solution. It's just that :) – Matías Fidemraizer Jan 24 '19 at 18:01
  • Thanks! Exactly what I needed! –  Jan 24 '19 at 18:04
  • @BattleDash You're welcome! Someone commented out your question and has pointed that you could use `Array#filter` . This might depend on your needs: if you need to mutate `input.users`, our conclusion is fine, otherwise, the other approach could be interesting :D – Matías Fidemraizer Jan 24 '19 at 18:08
0

Here's a quick tutorial for you: "Users" would be either an array (using []) or a javascript object (using {}), your choice. There won't be any actual tables unless you use a database instead of a JSON file (although if your JSON expression is as simple as your example, you could almost think of it as a table.) -- And actually, a third option would be to use the javascript Map type, which is like a beefed-up object, but I won't address that here.

While using an array would make it a bit easier to retrieve a list of data for all users (because arrays are simpler to iterate through), using an object would make it considerably easier to retrieve data for a single user (since you can directly specify the user you want by its key instead of needing to loop through the whole array until you find the one you want.) I'll show you an example that uses an object.

The individual user in your sample code is an example of a javascript object. JSON lets you convert an object to a string (for storage, I/O, and human readability) and back to an object (so javascript can understand it). You use the JSON.stringify() and JSON.parse() methods, respectively for these conversions. The string has to be JSON-formatted or this won't work, and your example is almost in JSON format.

To comply with JSON formatting, you could structure a Users object as follows. (Of course we're looking at the stringified version because mere humans can't easily read an "actual" javascript object):

"Users": {  // Each individual user is a property of your users object
  "780748c5d4504446bbba3114ce48f6e9":  // The Id is the key in the "key/value pair"
    { // The individual user object itself is the value in the key/value pair
    // Id is duplicated inside user for convenience (not necessarily the best way to do it)
      "id": "780748c5d4504446bbba3114ce48f6e9",
      "name": "ImBattleDash", // Each property of the user is also a key/value pair
      "discordId": "471621420162744342", //Commas separate the properties of an object
      "dateAdded": "1548295371" // All property values need double quotes for JSON compatibility
    }, // Commas separate the properties (ie the individual users) of the users object
  "446bbba3114ce48f6e9780748c5d4504": // This string is the second user's key
  {                                   // This object is the second user's value 
    "id": "446bbba3114ce48f6e9780748c5d4504",
    "name": "Wigwam",
    "discordId": "162744342471621420",
    "dateAdded": "1548295999"
  }
}

Once you retrieve the string from storage, you convert it to an object and delete a user as follows. (This is broken down into more steps than necessary for clarity.):

let usersObject = JSON.parse(stringRetrievedFromFile);
let userId = "780748c5d4504446bbba3114ce48f6e9";
let userToModifyOrDelete = usersObject[userId];
delete userToModifyOrDelete;

To change the user's discordId instead, you would do:

let discordId = userToModifyOrDelete.discordId; // Not necessary, just shows how to retrieve value
let newDiscordId = "whateverId";
userToModifyOrDelete.discordId = newDiscordId;

And you'd convert the object back into a string to store in your file with:

JSON.stringify(usersObject);

Hopefully that's almost all you need to know about JSON!

Cat
  • 4,141
  • 2
  • 10
  • 18
0

With great help from Cat and Matias I came up with this code that works!

    function findJson() {
    fs.readFile('./linkedusers.json', 'utf-8', function (err, data) {
        if (err) message.channel.send('Invalid Code.')

        var arrayOfObjects = JSON.parse(data)
        let findEntry = arrayOfObjects.users.find(entry => entry.discordId == myCode)

        const input = arrayOfObjects;

        const removeUser = (criteria, users) =>
        users.splice (users.indexOf (users.find (criteria)), 1)

        removeUser (
        ({ Id, discordId }) =>
            Id == findEntry.Id 
            && discordId == findEntry.discordId,
            input.users
        )

        console.log('unlinked')

        fs.writeFile('./linkedusers.json', JSON.stringify(arrayOfObjects, null, 4), 'utf-8', function(err) {
            if (err) throw err
            console.log('Done!')
        })


        let linkEmbed = new Discord.RichEmbed()
        .setTitle('Account unlinked!')
        .setDescription('Link your account by friending "BattleDash Bot" on Fortnite and then input the code you get messaged by typing "!link <code>"!')
        .setColor('#a900ff');

        message.channel.send({embed: linkEmbed});

    })
}