user11057786
user11057786

Reputation:

C# - How to delete a specific member in JSON File

I have this JSON file that stores Dokkan Passives for my Discord Bot for people to use and I recently added a Slash command where the user can Delete a passive based on the name they pass through it. If the name matches an entry in the JSON file then it can go ahead and delete the whole member from the JSON file, this is what I'm trying to do.

This is what part of my JSON File looks like

{
  "userPassiveStorage": "Storage for user created passives using /passivecreator",
  "members": [
    {
      "membersJSONList": [],
      "Error": null,
      "UserName": "𝕤𝕒𝕞.𝕛𝕖𝕤𝕦𝕤𝟠",
      "PassiveName": "TestTUR",
      "Rarity": "TUR",
      "UnitHP": 10000,
      "UnitATK": 19234,
      "UnitDEF": 14235,
      "UnitLeaderName": "A TUR Passive",
      "UnitLeaderSkill": 200,
      "UnitPassiveATK": 250,
      "UnitPassiveDEF": 150,
      "DmgReduction": 30,
      "Support": 30,
      "Links": "No active Links"
    },
    {
      "membersJSONList": [],
      "Error": null,
      "UserName": "𝕤𝕒𝕞.𝕛𝕖𝕤𝕦𝕤𝟠",
      "PassiveName": "TEQ Jiren",
      "Rarity": "LR",
      "UnitHP": 20863,
      "UnitATK": 21525,
      "UnitDEF": 14338,
      "UnitLeaderName": "Universe 11",
      "UnitLeaderSkill": 170,
      "UnitPassiveATK": 200,
      "UnitPassiveDEF": 200,
      "DmgReduction": 30,
      "Support": 0,
      "Links": "No active Links"
    }
  ]
}

I will explain what I'm trying to get this command to do

  1. User passes in the name of the passive they are trying to delete (This is the "PassiveName" property in the JSON file)
  2. Load the JSON and search for the passive based on that name
  3. If there is no entry that matches their search query then stop the command
  4. If there is a match, load that specific passive
  5. Delete it from the JSON file

This is my current method within a class where I can Load passives & hopefully Delete passives at the same time, it takes in a parameter object which loads in the already searched passive if Step 4 was successful

        public bool DeleteSpecificPassive(DokkanUserPassiveBuilder classObj)
        {
            try 
            {
                //var path = @"C:\Users\samue\Documents\Bot\bin\Debug\UserPassivesStorage.json";
                var path = @"D:\Visual Studio Projects\DiscordBotTest\bin\Debug\UserPassivesStorage.json";
                var json = File.ReadAllText(path);

                var jsonObj = JObject.Parse(json);

                var members = jsonObj["members"].ToObject<List<DokkanUserPassiveBuilder>>();
                if (members.Contains(classObj))
                {
                    members.Remove(classObj);
                    jsonObj["members"] = JArray.FromObject(members);

                    File.WriteAllText(path, jsonObj.ToString());
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex) 
            {
                Console.WriteLine(ex);
                Error = ex.ToString();
                return false;
            }
        }

For some reason, when I type in a correct passive name like "TEQ Jiren", even though it exists in the list, the if statement comparing the user input with the JSON file doesn't work and goes to the else block instead. So how can I get it so that the user input and the member in the class are compared and if it exists in the List then delete it and rewrite the JSON file?

If you want to view the full class for the bigger picture the Discord Bot is in my GitHub repo where I carry out these commands ->

[DokkanUserPassivesBuilder.cs] (https://github.com/samjesus8/CoolerDiscordBot/blob/master/Builders/DokkanUserPassiveBuilder.cs)

Upvotes: 0

Views: 104

Answers (2)

Kaneko Qt
Kaneko Qt

Reputation: 115

Why it may not work:

  1. In question you say that user passes the name of the passive they are trying to delete, but in code you pass whole object as argument (then are other fields empty?).

  2. As I see in code from GitHub you have provided, you are trying to compare objects of different classes, this will not work unless you have overridden Equals method.

  3. As I know objects by default are compared by reference, so even if you have two identical objects but they do not point to same object in heap, they considered as different objects.

How to fix this:

Consider using @vernou answer, it should be faster.

Using Linq to find object with provided PassiveName:

var found = members.FirstOrDefault(m => m.PassiveName == classObj.PassiveName);
if (found != null)
{
  members.Remove(found);
  jsonObj["members"] = JArray.FromObject(members);

  File.WriteAllText(path, jsonObj.ToString());
  return true;
}
else
{
  return false;
}

Upvotes: 1

vernou
vernou

Reputation: 7590

By defaut, the method Contains search by reference.

In the OP code :

var members = jsonObj["members"].ToObject<List<DokkanUserPassiveBuilder>>();

This generate new instances, distinct of classObj.

A solution, it's to search the index from a predicate and remove the element at the found index like :

var members = jsonObj["members"].ToObject<List<DokkanUserPassiveBuilder>>();
var indexToRemove = members.FindIndex(m => m.PassiveName == classObj.PassiveName)
if (indexToRemove != -1)
{
    members.RemoveAt(indexToRemove);

    jsonObj["members"] = JArray.FromObject(members);
    File.WriteAllText(path, jsonObj.ToString());
    return true;
}

Upvotes: 1

Related Questions