Search Unity

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

Discussion in 'Scripting' started by ddeo, Jun 6, 2017.

  1. ddeo

    ddeo

    Joined:
    Feb 17, 2013
    Posts:
    12
    [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
    Code (csharp):
    1.  
    2. { "name" : [
    3.     { "data" : "whatever"},
    4.     { "data" : "whatever"}
    5. ] }
    6. //instead of
    7. [
    8.     { "data" : "whatever"},
    9.     { "data" : "whatever"}
    10. ]
    11.  
    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

    Code (csharp):
    1.  
    2. Debug.Log(theobject.name.length); // returns 0
    3. //or
    4. Debug.Log(theobject.name[0]); // returns out of range
    5.  
    ========================================================
    my actual code for anyone wanting to look at it:
    Code (csharp):
    1.  
    2. {"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}]}]}
    3.  
    4.  
    Code (csharp):
    1.  
    2.  
    3. [Serializable]
    4. public class GameData {
    5.    public Xs map;
    6. }
    7.  
    8. [Serializable]
    9. public class Xs{
    10.    public Ys[] x;
    11. }
    12.  
    13. [Serializable]
    14. public class Ys{
    15.    public TileData[] y;
    16. }
    17.  
    18. [Serializable]
    19. public class TileData {
    20.    public Character contains;
    21.    public int x;
    22.    public int y;
    23. }
    24.  
    25. [Serializable]
    26. public class Character {
    27.    
    28.    public string id;
    29.    public string name;
    30.    public int hitPoints;
    31.     public int movement;
    32.     public int resWater;
    33.     public int resFire;
    34.     public int resLightning;
    35.    
    36.     public int currHitPoints;
    37.     public int currMovement;
    38.     public int currResWater;
    39.     public int currResFire;
    40.     public int currResLightning;
    41.    
    42.     public int delay;
    43.    
    44.     public Attack basic;
    45.     public Special special;
    46.    
    47.     public string owner;
    48.     public int x;
    49.     public int y;
    50.    
    51.     public string sprite;
    52.     public string avatar;
    53.  
    54. }
    55. [Serializable]
    56. public class Attack{
    57.  
    58.     public string type;
    59.     public int strength;
    60.     public int range;
    61.     public int delay;
    62. }
    63.  
    64. [Serializable]
    65. public class Special {
    66.     public string name;
    67.     public string type;
    68.     public int strength;
    69.     public int range;
    70.     public int delay;
    71.     public string[] specialEffect;
    72. }
    73.  
    74.  
    Code (csharp):
    1.  
    2. GameData game = JsonUtility.FromJson<GameData>(data); //where data is my json string
    3. //this never runs because game.map.x.Length comes back 0
    4. for (int x = 0; x < game.map.x.Length; x++){
    5.            for (int y = 0; y < game.map.x[x].y.Length; y++){
    6.                if (game.map.x[x].y[y].contains != null)
    7.                {
    8.                    //Character unit = new Character();
    9.                    Instantiate(test, Vector3.zero, Quaternion.identity);
    10.                }
    11.            }
    12.        }
    13.  
    14.  
     
  2. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Your class definitions don't quite match your JSON. The JSON is:

    Code (json):
    1. {
    2.    "x":[
    3.       {
    4.          "y":[
    5.             {
    6.                "x":0,
    7.                "y":0,
    8.                "contains":null
    9.             },
    10.             {
    11.                "x":0,
    12.                "y":1,
    13.                "contains":{
    14.                   "id":"5929d8a3c243d004cf4e569d.4",
    15.                   "name":"Archer",
    16.                   "movement":3, etc...
    Try something closer to this:
    Code (csharp):
    1.     [Serializable]
    2.     public class Y
    3.     {
    4.         public float x;
    5.         public float y;
    6.         // omitted rest for brevity
    7.     }
    8.  
    9.     [Serializable]
    10.     public class X
    11.     {
    12.         public Y[] y;
    13.     }
    14.  
    15.     [Serializable]
    16.     public class GameData
    17.     {
    18.         public X[] x;
    19.     }
    20.  
    21.     public GameData game;
    22.  
    23.     void Start () {
    24.         game = JsonUtility.FromJson<GameData>(data);  
    25.     }
     
  3. ddeo

    ddeo

    Joined:
    Feb 17, 2013
    Posts:
    12
    Sorry I printed the JSON string wrong in the debug there is actually a "map" inside it...

    Code (csharp):
    1.  
    2. {"map":
    3.      {"x":[
    4.           {"y":[
    5.                {
    6.                 "x":0,
    7.                 "y":0,
    8.                 "contains":null
    9.                },
    10.                {
    11.                  "x":0,
    12.                  //etc
    13.  
     
  4. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,187
    So...what's the question exactly? Once the json string is cast into a variable, you just access the array through the variable.
     
  5. ddeo

    ddeo

    Joined:
    Feb 17, 2013
    Posts:
    12
    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 :(

    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[x].y[y].contains, it will complain index out of range.

    Sorry if I was unclear.
     
  6. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    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.
     
  7. ddeo

    ddeo

    Joined:
    Feb 17, 2013
    Posts:
    12
    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!
     
  8. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,694
    Glad you got it figured out! I think we all do that kind of thing on occasion.
     
  9. akhileshunity

    akhileshunity

    Joined:
    Dec 4, 2019
    Posts:
    1