JSON and arrays; how to get length and reference by index?

[I’m not sure if I am doing this right all I could understand about the subject is I can’t have top level arrays so it should be

{ "name" : [
    { "data" : "whatever"},
    { "data" : "whatever"}
] }
//instead of 
[
    { "data" : "whatever"},
    { "data" : "whatever"}
]

and JsonUtility should work right?

But I am having trouble getting the length and the reference by index of the array after using the fromjson function in this example something like

Debug.Log(theobject.name.length); // returns 0
//or 
Debug.Log(theobject.name[0]); // returns out of range

========================================================
my actual code for anyone wanting to look at it:

{"x":[{"y":[{"x":0,"y":0,"contains":null},{"x":0,"y":1,"contains":{"id":"5929d8a3c243d004cf4e569d.4","name":"Archer","movement":3,"resWater":25,"resFire":25,"resLightning":25,"currHitPoints":100,"currMovement":3,"currResWater":25,"currResFire":25,"currResLightning":25,"delay":0,"basic":{"type":"water","strength":25,"range":2,"delay":25},"special":{"name":"aim","type":"water","strength":40,"range":2,"delay":50,"specialEffect":null},"owner":"5929d8a3c243d004cf4e569d","x":0,"y":1}},{"x":0,"y":2,"contains":null},{"x":0,"y":3,"contains":null},{"x":0,"y":4,"contains":null},{"x":0,"y":5,"contains":null},{"x":0,"y":6,"contains":{"id":"592f3a947d990b6bb5d95a30.3","name":"Knight","movement":2,"resWater":15,"resFire":25,"resLightning":35,"currHitPoints":150,"currMovement":2,"currResWater":15,"currResFire":25,"currResLightning":35,"delay":0,"basic":{"type":"water","strength":25,"range":2,"delay":25},"special":{"name":"aim","type":"water","strength":40,"range":2,"delay":50,"specialEffect":null},"owner":"592f3a947d990b6bb5d95a30","x":0,"y":6}},{"x":0,"y":7,"contains":null}]},{"y":[{"x":1,"y":0,"contains":null},{"x":1,"y":1,"contains":{"id":"5929d8a3c243d004cf4e569d.0","name":"Knight","movement":2,"resWater":15,"resFire":25,"resLightning":35,"currHitPoints":150,"currMovement":2,"currResWater":15,"currResFire":25,"currResLightning":35,"delay":0,"basic":{"type":"water","strength":25,"range":2,"delay":25},"special":{"name":"aim","type":"water","strength":40,"range":2,"delay":50,"specialEffect":null},"owner":"5929d8a3c243d004cf4e569d","x":1,"y":1}},{"x":1,"y":2,"contains":null},{"x":1,"y":3,"contains":null},{"x":1,"y":4,"contains":null},{"x":1,"y":5,"contains":null},{"x":1,"y":6,"contains":null},{"x":1,"y":7,"contains":null}]},{"y":[{"x":2,"y":0,"contains":null},{"x":2,"y":1,"contains":null},{"x":2,"y":2,"contains":null},{"x":2,"y":3,"contains":null},{"x":2,"y":4,"contains":null},{"x":2,"y":5,"contains":null},{"x":2,"y":6,"contains":{"id":"592f3a947d990b6bb5d95a30.2","name":"Longbowman","movement":3,"resWater":25,"resFire":25,"resLightning":25,"currHitPoints":80,"currMovement":3,"currResWater":25,"currResFire":25,"currResLightning":25,"delay":0,"basic":{"type":"water","strength":25,"range":2,"delay":25},"special":{"name":"aim","type":"water","strength":40,"range":2,"delay":50,"specialEffect":null},"owner":"592f3a947d990b6bb5d95a30","x":2,"y":6}},{"x":2,"y":7,"contains":null}]},{"y":[{"x":3,"y":0,"contains":null},{"x":3,"y":1,"contains":{"id":"5929d8a3c243d004cf4e569d.1","name":"Archer","movement":3,"resWater":25,"resFire":25,"resLightning":25,"currHitPoints":100,"currMovement":3,"currResWater":25,"currResFire":25,"currResLightning":25,"delay":0,"basic":{"type":"water","strength":25,"range":2,"delay":25},"special":{"name":"aim","type":"water","strength":40,"range":2,"delay":50,"specialEffect":null},"owner":"5929d8a3c243d004cf4e569d","x":3,"y":1}},{"x":3,"y":2,"contains":null},{"x":3,"y":3,"contains":null},{"x":3,"y":4,"contains":null},{"x":3,"y":5,"contains":null},{"x":3,"y":6,"contains":null},{"x":3,"y":7,"contains":null}]},{"y":[{"x":4,"y":0,"contains":null},{"x":4,"y":1,"contains":null},{"x":4,"y":2,"contains":null},{"x":4,"y":3,"contains":null},{"x":4,"y":4,"contains":null},{"x":4,"y":5,"contains":null},{"x":4,"y":6,"contains":{"id":"592f3a947d990b6bb5d95a30.1","name":"Archer","movement":3,"resWater":25,"resFire":25,"resLightning":25,"currHitPoints":100,"currMovement":3,"currResWater":25,"currResFire":25,"currResLightning":25,"delay":0,"basic":{"type":"water","strength":25,"range":2,"delay":25},"special":{"name":"aim","type":"water","strength":40,"range":2,"delay":50,"specialEffect":null},"owner":"592f3a947d990b6bb5d95a30","x":4,"y":6}},{"x":4,"y":7,"contains":null}]},{"y":[{"x":5,"y":0,"contains":null},{"x":5,"y":1,"contains":{"id":"5929d8a3c243d004cf4e569d.2","name":"Longbowman","movement":3,"resWater":25,"resFire":25,"resLightning":25,"currHitPoints":80,"currMovement":3,"currResWater":25,"currResFire":25,"currResLightning":25,"delay":0,"basic":{"type":"water","strength":25,"range":2,"delay":25},"special":{"name":"aim","type":"water","strength":40,"range":2,"delay":50,"specialEffect":null},"owner":"5929d8a3c243d004cf4e569d","x":5,"y":1}},{"x":5,"y":2,"contains":null},{"x":5,"y":3,"contains":null},{"x":5,"y":4,"contains":null},{"x":5,"y":5,"contains":null},{"x":5,"y":6,"contains":null},{"x":5,"y":7,"contains":null}]},{"y":[{"x":6,"y":0,"contains":null},{"x":6,"y":1,"contains":null},{"x":6,"y":2,"contains":null},{"x":6,"y":3,"contains":null},{"x":6,"y":4,"contains":null},{"x":6,"y":5,"contains":null},{"x":6,"y":6,"contains":{"id":"592f3a947d990b6bb5d95a30.0","name":"Knight","movement":2,"resWater":15,"resFire":25,"resLightning":35,"currHitPoints":150,"currMovement":2,"currResWater":15,"currResFire":25,"currResLightning":35,"delay":0,"basic":{"type":"water","strength":25,"range":2,"delay":25},"special":{"name":"aim","type":"water","strength":40,"range":2,"delay":50,"specialEffect":null},"owner":"592f3a947d990b6bb5d95a30","x":6,"y":6}},{"x":6,"y":7,"contains":null}]},{"y":[{"x":7,"y":0,"contains":null},{"x":7,"y":1,"contains":{"id":"5929d8a3c243d004cf4e569d.3","name":"Knight","movement":2,"resWater":15,"resFire":25,"resLightning":35,"currHitPoints":150,"currMovement":2,"currResWater":15,"currResFire":25,"currResLightning":35,"delay":0,"basic":{"type":"water","strength":25,"range":2,"delay":25},"special":{"name":"aim","type":"water","strength":40,"range":2,"delay":50,"specialEffect":null},"owner":"5929d8a3c243d004cf4e569d","x":7,"y":1}},{"x":7,"y":2,"contains":null},{"x":7,"y":3,"contains":null},{"x":7,"y":4,"contains":null},{"x":7,"y":5,"contains":null},{"x":7,"y":6,"contains":{"id":"592f3a947d990b6bb5d95a30.4","name":"Archer","movement":3,"resWater":25,"resFire":25,"resLightning":25,"currHitPoints":100,"currMovement":3,"currResWater":25,"currResFire":25,"currResLightning":25,"delay":0,"basic":{"type":"water","strength":25,"range":2,"delay":25},"special":{"name":"aim","type":"water","strength":40,"range":2,"delay":50,"specialEffect":null},"owner":"592f3a947d990b6bb5d95a30","x":7,"y":6}},{"x":7,"y":7,"contains":null}]}]}
[Serializable]
public class GameData {
   public Xs map;
}

[Serializable]
public class Xs{
   public Ys[] x;
}

[Serializable]
public class Ys{
   public TileData[] y;
}

[Serializable]
public class TileData {
   public Character contains;
   public int x;
   public int y;
}

[Serializable]
public class Character {
   
   public string id;
   public string name;
   public int hitPoints;
    public int movement;
    public int resWater;
    public int resFire;
    public int resLightning;
   
    public int currHitPoints;
    public int currMovement;
    public int currResWater;
    public int currResFire;
    public int currResLightning;
   
    public int delay;
   
    public Attack basic;
    public Special special;
   
    public string owner;
    public int x;
    public int y;
   
    public string sprite;
    public string avatar;

}
[Serializable]
public class Attack{

    public string type;
    public int strength;
    public int range;
    public int delay;
}

[Serializable]
public class Special {
    public string name;
    public string type;
    public int strength;
    public int range;
    public int delay;
    public string[] specialEffect;
}
GameData game = JsonUtility.FromJson<GameData>(data); //where data is my json string
//this never runs because game.map.x.Length comes back 0
for (int x = 0; x < game.map.x.Length; x++){
           for (int y = 0; y < game.map.x[x].y.Length; y++){
               if (game.map.x[x].y[y].contains != null)
               {
                   //Character unit = new Character();
                   Instantiate(test, Vector3.zero, Quaternion.identity);
               }
           }
       }

Your class definitions don’t quite match your JSON. The JSON is:

{
   "x":[
      {
         "y":[
            {
               "x":0,
               "y":0,
               "contains":null
            },
            {
               "x":0,
               "y":1,
               "contains":{
                  "id":"5929d8a3c243d004cf4e569d.4",
                  "name":"Archer",
                  "movement":3, etc...

Try something closer to this:

    [Serializable]
    public class Y
    {
        public float x;
        public float y;
        // omitted rest for brevity
    }

    [Serializable]
    public class X
    {
        public Y[] y;
    }

    [Serializable]
    public class GameData
    {
        public X[] x;
    }

    public GameData game;

    void Start () {
        game = JsonUtility.FromJson<GameData>(data);  
    }

Sorry I printed the JSON string wrong in the debug there is actually a “map” inside it…

{"map":
     {"x":[
          {"y":[
               {
                "x":0,
                "y":0,
                "contains":null
               },
               {
                 "x":0,
                 //etc

So…what’s the question exactly? Once the json string is cast into a variable, you just access the array through the variable.

the question really is am I doing it wrong because it wont let me access it the way I think it should be…
If I am doing it right then why isn’t it working as expected :frowning:

In the original post, in the last code section in the for loop. the array length comes back 0 so it doesn’t run it despite the data having 8 entries in that array or its what I expect it to have.
If I try to access game.map.x[×].y[y].contains, it will complain index out of range.

Sorry if I was unclear.

My example code above defines a public variable game. The Start method calls JsonUtility.FromJson to set this variable. You could do something similar so you can inspect the contents of game in the inspector to confirm that it contains what you expect.

Thanks for that tip TonyLi, I figured it out.

So apparently I had game as a public var (though I forgot I can check the inspector) but when I was calling FromJson, I was redeclaring it making a local variable… then I was accessing what I thought was the correct one from a different function and it was giving me the public 0 length GameData.map.x variable. (I placed them side by side in the showcase thinking that wasn’t the problem my bad.

Just had to take out the GameData redeclaration and it works correctly now.

Silly me, thank you very much!

Glad you got it figured out! I think we all do that kind of thing on occasion.

:hushed: