Bunny83 / SimpleJSON

A simple JSON parser in C#
MIT License
735 stars 294 forks source link

Remove() not working? #27

Closed Shadowing1983 closed 4 years ago

Shadowing1983 commented 4 years ago

Say my JSONNode looks like this

                ActiveGroups["Groups"]["Steubers"]["Names"][0] = "John";
                ActiveGroups["Groups"]["Steubers"]["Names"][1] = "Paul";
                ActiveGroups["Groups"]["Steubers"]["Names"][2] = "Robert";
                ActiveGroups["Groups"]["Steubers"]["Names"][3] = "Cindy";

                ActiveGroups["Groups"]["Steubers"]["PlayersLeft"][0] = "John";
                ActiveGroups["Groups"]["Steubers"]["PlayersLeft"][1] = "Paul";
                ActiveGroups["Groups"]["Steubers"]["PlayersLeft"][2] = "Robert";
                ActiveGroups["Groups"]["Steubers"]["PlayersLeft"][3] = "Cindy";

                ActiveGroups["Groups"]["Steubers"]["NamesLeft"][0] = "John";
                ActiveGroups["Groups"]["Steubers"]["NamesLeft"][1] = "Paul";
                ActiveGroups["Groups"]["Steubers"]["NamesLeft"][2] = "Robert";
                ActiveGroups["Groups"]["Steubers"]["NamesLeft"][3] = "Cindy";

        ActiveGroups["Groups"][GameSettings.CurrentSelectedGroupName]["PlayersLeft"].Remove(2);

This will remove key 2 from Names, PlayersLeft and NamesLeft should only be removing it from PlayersLeft

Bunny83 commented 4 years ago

That's not possible unless you manually created and copied the JSONArray from Names to PlayersLeft and to NamesLeft so all reference the same JSONArray. The code you've shown, assuming none of these keys exist yet, will create 3 individual arrays. Calling Remove on one of them does not affect the others.

Note that your code is a bit dangerous. This line:

ActiveGroups["Groups"]["Steubers"]["Names"][0] = "John";

does not set the element at index 0 but since the index is out of bounds it will actually add the item to the end of the list. Integer numbers do not denote keys but indices of an array. You can not directly set for example index 42. This is not a dictionary, it's an array.

I just tried your code and if I serialize the ActiveGroups object to json I get:


{
   "Groups" : {
      "Steubers" : {
         "Names" : [
            "John",
            "Paul",
            "Robert",
            "Cindy"
         ],
         "PlayersLeft" : [
            "John",
            "Paul",
            "Robert",
            "Cindy"
         ],
         "NamesLeft" : [
            "John",
            "Paul",
            "Robert",
            "Cindy"
         ]
      }
   }
}

Before I call Remove and when calling

ActiveGroups["Groups"]["Steubers"]["PlayersLeft"].Remove(2);

I get this:

{
   "Groups" : {
      "Steubers" : {
         "Names" : [
            "John",
            "Paul",
            "Robert",
            "Cindy"
         ],
         "PlayersLeft" : [
            "John",
            "Paul",
            "Cindy"
         ],
         "NamesLeft" : [
            "John",
            "Paul",
            "Robert",
            "Cindy"
         ]
      }
   }
}

So as you can see the 3rd element of "PlayersLeft" has been removed but not the others. So I can not reproduce your issue with your provided code.

Bunny83 commented 4 years ago

Note when you do something like this:

    var ActiveGroups = new JSONObject();
    ActiveGroups["Groups"]["Steubers"]["Names"][0] = "John";
    ActiveGroups["Groups"]["Steubers"]["Names"][1] = "Paul";
    ActiveGroups["Groups"]["Steubers"]["Names"][2] = "Robert";
    ActiveGroups["Groups"]["Steubers"]["Names"][3] = "Cindy";

    ActiveGroups["Groups"]["Steubers"]["PlayersLeft"] = ActiveGroups["Groups"]["Steubers"]["Names"];
    ActiveGroups["Groups"]["Steubers"]["NamesLeft"] = ActiveGroups["Groups"]["Steubers"]["Names"];

Of course deleting one element from one array will affect all 3 arrays since there is only one array and we just put it into several subtrees. This is generally not recommended and you should be careful when you manually move reference objects around. For example this would cause a stackoverflow:

var node = new JSONObject();
node["subNode"] = node;

It's essentially an object that contains itself as child and thus creates an infinite recursion. When you use ToString on that you get a stack overflow.

I just realised that a Clone method might be useful, so I just added one. The Clone method will recursively clone an entire node tree. So in case you want to "re-add" a sub tree again to the same tree you can use the Clone method to do so.

Shadowing1983 commented 4 years ago

you are awesome man. I'm just a huge fan of SimpleJSON btw. I like how you had to go look further into how I was getting that result lol. For me not knowing what you all just told me you can understand how it was looking like a impossible thing on my end too. I even showed my problem to a friend of mine that doesn't use JSONNode but is way knowledgeable than me in coding and he was wondering what the heck.

Ok you are 100% right. Thats what I'm doing. I'm copying a JSONNode and adding to another one. Even though you just explained why that doesn't make sense to me lol. So when I copy it like that both those arrays are some how linked? Must be a back end thing cause when I console.log it looks fine.

You just showed me how to do something I've been wanting to know for a long time. Really needs to be a few more examples on the wiki.

I didn't know how to create a JSONNode. This entire time I've been having to do

JSONNode NewNode = JSON.Parse("{}");

This is because I'm always using JSONNode coming from my server. But now these days I use it for a lot of stuff lol. I see now i can do new JSONObject();

Then I can just start adding things to it like

NewNode["Colors"] = new JSONArray();
Shadowing1983 commented 4 years ago
GameData["Names"] = new JSONArray();

JSONNode PlayersLeft = new JSONObject();
PlayersLeft = GameData["Names"].AsArray;
[GameData"] ["PlayersLeft"] = PlayersLeft;

So you are saying this is how you clone? Cause I still have the issue with remove() when I do it this way.

Bunny83 commented 4 years ago

No, you actually store the same array which you have in the "Names" key in the PlayersLeft key. So both contain the same array. If you want to clone / duplicate a node you can just use

GameData["Names"] = new JSONArray();

JSONNode PlayersLeft = GameData["Names"].Clone();
GameData["PlayersLeft"] = PlayersLeft;

Note that your code looks strange anyways. Why did you create a new "JSONObject" when you then replace the content of the variable with the JSONArray of the "Names" key?

Shadowing1983 commented 4 years ago

I was trying to duplicate it with out it being connected to the other array like you was saying lol. It wasn't my original code. :)

I guess i thought thats what you was saying. I just had to declare a new JSONNode to prevent it. Thanks for adding the Clone method. Your a good guy.