Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Working with top level JSON arrays in Unity

Discussion in 'Scripting' started by Zante, Nov 9, 2020.

  1. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    I'm trying to parse a JSON array containing some user properties. I'm having real trouble loading it into a simple class structure.

    My json looks like:
    Code (JavaScript):
    1. [
    2. {"id":"Jcb0eLG7ZNhsL30yAAAA","nickName":"Unnamed","posX":0,"posY":0,"posZ":0,"rotY":0},
    3. {"id":"F_JwdCJvOhkWTG_2AAAB","nickName":"Unnamed","posX":0,"posY":0,"posZ":0,"rotY":0},
    4. {"id":"Y-zbT0ONDD6ehB7wAAAF","nickName":"Unnamed","posX":0,"posY":0,"posZ":0,"rotY":0}
    5. ]
    The class I'm trying to move the data into looks like this:
    Code (CSharp):
    1. public class PlayerClass
    2. {
    3.     public string id;
    4.     public string nickName;
    5.     public float posX;
    6.     public float posY;
    7.     public float posZ;
    8.     public float rotY;
    9. }
    I'm trying to convert the JSON data by doing:
    Code (CSharp):
    1. PlayerClass[] test = JsonUtility.FromJson<PlayerClass[]>(json);
    2. Debug.Log(test[0].nickName);

    I'm using Unit 2018.4.11f1 and nothing seems to work. :[

    The error I'm getting reads:
    JSON must represent an object type.   at (wrapper managed-to-native) UnityEngine.JsonUtility.FromJsonInternal(string,object,System.Type)
     
  2. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,260
    Top level arrays are not supported by JsonUtility. You need to use a wrapper for the array for it to work.

    I use this class to have arrays work with JsonUtility.
    Code (CSharp):
    1. [System.Serializable]
    2. public class Wrapper<T>
    3. {
    4.     public T[] array;
    5. }
    6.  
    7. //Use
    8.  
    9. PlayerClass[] test = new PlayerClass[3];
    10.  
    11. //Add data to array
    12.  
    13. Wrapper<PlayerClass> wrapper = new Wrapper<PlayerClass>();
    14. wrapper.array = test;
    15.  
    16. string json = JsonUtility.ToJson(wrapper);
    17.  
    18. PlayerClass[] fromJsonTest = JsonUtility.FromJson<Wrapper<PlayerClass>>(json);
    19.  
    Or use an alternative serialization system that supports top level arrays.
     
    Bunny83, Zante and eses like this.
  3. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
  4. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    I did, the post got a little off topic towards the end though. Similarly, the issue goes back some years and has been on the roadmap for a fix but none is present yet. You are right though, duplicates aren't needed and I removed my reply in the old thread.
     
  5. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @Zante

    Well anyway, I think the only way you can get your de/serialization work with arrays/lists (with JsonUtility) is by using class to wrap an array or a list like @Chris-Trueman said.

    Of course if you don't use JsonUtility and use something else like JSON.NET or SimpleJSON, then things probably work differently. But personally I like Unity JSON serializer as it is very easy to deserialize json back to objects.
     
  6. Zante

    Zante

    Joined:
    Mar 29, 2008
    Posts:
    429
    FIXED:

    I revised things a little to reflect the setup below (same JSON data):

    Code (CSharp):
    1. [Serializable]
    2. public class AllConnectedPlayers
    3. {
    4.     public PlayerClass[] allConnectedPlayers;
    5. }
    6.  
    7. [Serializable]
    8. public class PlayerClass
    9. {
    10.     public string id;
    11.     public string nickName;
    12.     public float posX;
    13.     public float posY;
    14.     public float posZ;
    15.     public float rotY;
    16. }
    The code to parse the JSON data (stored in json as a string):

    Code (CSharp):
    1.         AllConnectedPlayers myObject = JsonUtility.FromJson<AllConnectedPlayers>("{\"allConnectedPlayers\":" + json + "}");
    2.         Debug.Log(myObject.allConnectedPlayers.Length);
    3.         Debug.Log(myObject.allConnectedPlayers[0].nickName);
     
    Last edited: Nov 9, 2020