1. Help us improve the editor usability and artist workflows. Join our discussion to provide your feedback.
    Dismiss Notice
  2. We're looking for feedback on Unity Starter Kits! Let us know what you’d like.
    Dismiss Notice
  3. We’re giving 2017.1 beta testers a chance to win t-shirts and a Nintendo Switch. Read more on the blog.
    Dismiss Notice
  4. Unity 2017.1 beta is now available for download.
    Dismiss Notice
  5. Unity 5.6 is now released.
    Dismiss Notice
  6. Get further faster with the Unity Plus Accelerator Pack, free for new Unity Plus subscribers for a limited time. Click here for more details.
    Dismiss Notice
  7. Check out all the fixes for 5.6 on the patch releases page.
    Dismiss Notice
  8. Learn how you'll soon be able to publish your games to China in four simple steps with Xiaomi. Sign up now for early access.
    Dismiss Notice

How to load an array with JsonUtility?

Discussion in 'Scripting' started by IntDev, Dec 23, 2015.

  1. IntDev

    IntDev

    Joined:
    Jan 14, 2013
    Posts:
    152
    I have a json array like this:
    Code (CSharp):
    1. [
    2.     {
    3.         "key": "here's the key",
    4.     },
    5.     {
    6.         "key": "here's the key",
    7.     }
    8. ]
    I try to load like this:
    Code (CSharp):
    1. [Serializable]
    2. public class Info
    3. {
    4.     public string key;
    5. }
    6.  
    7. var asset = Resources.Load<TextAsset>("JsonTest");
    8. var info = JsonUtility.FromJson<Info[]>(asset.text);
    But it says like this:
     
  2. Polymorphik

    Polymorphik

    Joined:
    Jul 25, 2014
    Posts:
    591
    Did you make the json yourself?
     
  3. IntDev

    IntDev

    Joined:
    Jan 14, 2013
    Posts:
    152
    yes
     
  4. Polymorphik

    Polymorphik

    Joined:
    Jul 25, 2014
    Posts:
    591
    is asset null by any chance?
     
  5. IntDev

    IntDev

    Joined:
    Jan 14, 2013
    Posts:
    152
    Nope ;)
     
  6. Polymorphik

    Polymorphik

    Joined:
    Jul 25, 2014
    Posts:
    591
    try inheriting from System.Object
     
  7. IntDev

    IntDev

    Joined:
    Jan 14, 2013
    Posts:
    152
    Nothing different. If I print .Lenght it says 174090232 :eek:
     
  8. Polymorphik

    Polymorphik

    Joined:
    Jul 25, 2014
    Posts:
    591
  9. superpig

    superpig

    Insert bacon, receive bugfix Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    3,746
    Hi,

    We currently do not support array types for top-level JSON deserialization (like Info[]). You need to wrap the JSON in an object, like this:

    Code (csharp):
    1.  
    2. { "infos": [
    3.    { "key" : "key 1" },
    4.    { "key" : "key 2" }
    5. ] }
    6.  
    and then make a little wrapper class to match:
    Code (csharp):
    1.  
    2. [Serializable]
    3. public class InfosCollection
    4. {
    5.    public Info[] infos;
    6. }
    7.  
    8. JsonUtility.FromJson<InfosCollection>(...);
    9.  
    We know that this is not ideal and it's on the list to handle top-level arrays properly in the future.
     
  10. abdulthegamer

    abdulthegamer

    Joined:
    Sep 14, 2013
    Posts:
    4
    Thanks for the instructions Richard, Can you give an example on how to retrieve value for individual key such that a row has more than one key and its respective values. ?

    Ex :
    {
    "object":
    {
    "name": "nm",
    "place": "plc",
    "description": "dscrptn",
    },
    {
    "name": "nm",
    "place": "plc",
    "description": "dscrptn",
    },
    {
    "name": "nm",
    "place": "plc",
    "description": "dscrptn",
    },
    etc
    }
    How to access each values or say in a loop or something like that ?
     
    Last edited: Feb 3, 2016
  11. superpig

    superpig

    Insert bacon, receive bugfix Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    3,746
    Code (csharp):
    1.  
    2. [System.Serializable]
    3. public struct MyObject
    4. {
    5.    [System.Serializable]
    6.    public struct ArrayEntry
    7.    {
    8.       public string name;
    9.       public string place;
    10.       public string description;
    11.    }
    12.  
    13.    public ArrayEntry[] object;
    14. }
    15.  
     
    rakkarage likes this.
  12. garrido86

    garrido86

    Joined:
    Dec 17, 2013
    Posts:
    153
    I made this helper method to wrap a json around a class, this way you don't need to change code on the server for accommodating the json top-level array problem .

    Code (CSharp):
    1.     public static string WrapToClass(this string source, string topClass){
    2.         return string.Format("{{ \"{0}\": {1}}}", topClass, source);
    3.     }
     
    Last edited: Mar 9, 2016
  13. Meizi-Games

    Meizi-Games

    Joined:
    Nov 27, 2014
    Posts:
    4
    Took me a while to notice that FromJson doesn't work if the class members are defined as properties
     
    Artyom-Abgaryan likes this.
  14. superpig

    superpig

    Insert bacon, receive bugfix Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    3,746
    Correct; same as the Inspector.
     
  15. ffleurey

    ffleurey

    Joined:
    Apr 4, 2016
    Posts:
    1
    I wrote a little workaround:
    Code (CSharp):
    1. public class JsonHelper
    2. {
    3.     public static T[] getJsonArray<T>(string json)
    4.     {
    5.         string newJson = "{ \"array\": " + json + "}";
    6.         Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>> (newJson);
    7.         return wrapper.array;
    8.     }
    9.  
    10.     [Serializable]
    11.     private class Wrapper<T>
    12.     {
    13.         public T[] array;
    14.     }
    15. }
    You can now simple deserialize like this:
    Code (CSharp):
    1. YouObject[] objects = JsonHelper.getJsonArray<YouObject> (jsonString);
    Very surprising a such basic feature is not implemented...
     
    akasurreal, ina, Andrew915 and 8 others like this.
  16. jplanders

    jplanders

    Joined:
    Apr 8, 2016
    Posts:
    1
    This worked beautifully! Thanks ffleurey
     
  17. ImFromTheFuture

    ImFromTheFuture

    Joined:
    May 21, 2015
    Posts:
    17
    Hi, this helped a lot. Thank you!
     
  18. Dazzid

    Dazzid

    Joined:
    Apr 15, 2014
    Posts:
    61
    Hi,
    I'm trying this answer, but have doubts about how to properly set YouObject[]?
    Thanks for the help
     
    Krish-Vikram likes this.
  19. elektronische

    elektronische

    Joined:
    Nov 27, 2014
    Posts:
    43
    JSON Utility class doesn't support Array types or List yet?

    I'm trying something like this to use Lists and seems to work well, but i'm not sure if is a good implementation:

    Code (CSharp):
    1. [System.Serializable]
    2. public class PlayerStats{
    3.  
    4. public int life;
    5. public string name;
    6. public int energy;
    7. }
    Then,
    Code (CSharp):
    1. [System.Serializable]
    2. public class PlayerStatsList {
    3.  
    4.     public List <PlayerStats> playerStats;
    5. }
    Now, in the class that i wan't to access to the JSON File:
    Code (CSharp):
    1. public PlayerStatsList myPlayerStatsList = new PlayerStatsList();
    2.  
    3. JsonUtility.FromJsonOverwrite (jsonText, myPlayerStatsList);
    4.  
    With this, i have all the info loaded from the JSON file in the list myPlayerStatsList.playerStats.

    The JSON File must have the same structure that the PlayerStats class, like this:
    Code (CSharp):
    1. {
    2.     "PlayerStats": [
    3.         {
    4.             "life": "10",
    5.             "name": "Kratos",
    6.             "energy": 100
    7.         },
    8.         {
    9.             "life": "80",
    10.             "name": "Nathan",
    11.             "energy": 20
    12.         },
    13.         {
    14.             "life": "90",
    15.             "name": "Link",
    16.             "energy": 25
    17.         }
    18.     ]
    19. }
     
    Last edited: Aug 8, 2016
  20. Search

    Search

    Joined:
    Jul 24, 2014
    Posts:
    41
    Simple and clever, Thanks !
     
  21. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,847
    If you use this free Unity-compatible fork of Newtonsoft's JSON.NET, then everything just works as you'd expect. There's a good reason even Microsoft recommends using this third-party solution rather than .NET's built-in options!

    https://github.com/SaladLab/Json.Net.Unity3D

    Code (csharp):
    1. PlayerStats[] statArray = JsonConvert.DeserializeObject<PlayerStats[]>(json);
     
  22. Krish-Vikram

    Krish-Vikram

    Joined:
    Aug 17, 2012
    Posts:
    5
    Is it working ?
    Its not Working for me :/
     
  23. rdvt

    rdvt

    Joined:
    Aug 23, 2014
    Posts:
    21
    Thanks, it work!!!!
     
  24. herosf2006

    herosf2006

    Joined:
    Nov 9, 2016
    Posts:
    4

    It's helpful, but how to make a file like ur file [PlayerStats].
     
  25. metaphysician

    metaphysician

    Joined:
    May 29, 2012
    Posts:
    87
    hey everyone! - i'm having a bit of trouble on the deserializing front. here's the basic array format in text file. note that my code doesn't contain the indents or line breaks - i assume that's not important? i'm breaking it up here so you can see the basic structure:
    Code (JavaScript):
    1.  
    2. {
    3. "SavedLayer":[
    4. {
    5. "layerName":"Layer_0",
    6. "instrumentNumber":0,
    7. "seqLength":7,
    8. "timeDivision":8,
    9. "gateTime":0.30000001192092898,
    10. "noteRowAssign":[30,42,44,46,47,59,63,80]
    11. },
    12. {"layerName":"Layer_1",
    13. "instrumentNumber":1,
    14. "seqLength":8,
    15. "timeDivision":16,
    16. "gateTime":0.30000001192092898,
    17. "noteRowAssign":[40,42,43,44,46,48,49,51]
    18. },
    19. ]
    20.  
    21. }
    i'm trying to retrieve it like this:

    Code (CSharp):
    1.  
    2. string AllTheData=File.ReadAllText(filename);
    3. SavedLayer[] data=JsonHelper.getJsonArray<SavedLayer>(AllTheData);
    SavedLayer is the basic class i created to store each object's data in JSON. it validates in JSON Lint as well. however if i try to get the first object in the array using this method, i get 'unexpected node type' and a Null Ref on the Debug.Log statement.

    any clue what i'm doing wrong here?
     
    Last edited: Nov 27, 2016
  26. superpig

    superpig

    Insert bacon, receive bugfix Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    3,746
    ffleurey's JsonHelper code expects the top-level array to be called 'array', not 'SavedLayer.'
     
  27. metaphysician

    metaphysician

    Joined:
    May 29, 2012
    Posts:
    87
    hmm - well looking at it after some sleep it actually looks like it wraps the '['and ']' that begin and end the array with '{ array:' and '}'. which technically means i don't have to bother as long as my array begins and ends with square brackets. but i'm still having a lot of trouble understanding the deserialization process. i went back to the Scripting API for retrieving JSON data (https://docs.unity3d.com/ScriptReference/JsonUtility.FromJson.html). i've given it a try, but my code is definitely not working. the main bit is here:

    Code (CSharp):
    1.     public static DataManager.SavedLayer readLayerJSON(string dataString)
    2.     {
    3.         string AllTheData = File.ReadAllText(DataManager.filenamePath());
    4.         allLayers = JsonHelper.getJsonArray<DataManager.SavedLayer>(AllTheData);
    5.  
    6.         for (int count=0; count <8; count++)
    7.         {
    8.             return JsonUtility.FromJson<DataManager.SavedLayer>(dataString);
    9.         }
    10.  
    11.     }
    i'm obviously getting confused about what all the data(aka AllTheData) is vs parsing out each individual JSON object within the data. is it possible to retrieve all data for all objects at once without having to loop? this code fails but all my fixes so far aren't doing the trick. i want to copy each Layer object's JSON data to each element of allLayers, which is an array of DataManager.SavedLayer classes. assistance appreciated!
     
  28. Artyom-Abgaryan

    Artyom-Abgaryan

    Joined:
    Jan 9, 2010
    Posts:
    123
    ADD THAT INTO DOCUMENTATION !!!!

    There is no mention about properties in docs. So you can save developers' time and Karma of unitech :D
     
    bik3r014 and wendigo like this.
  29. Andrew915

    Andrew915

    Joined:
    Mar 4, 2017
    Posts:
    2

    It works like charm ,man (Y) hope it wouldn't fail in any case Thanku
     
  30. Sarudil

    Sarudil

    Joined:
    Mar 3, 2017
    Posts:
    6
  31. coderlaze

    coderlaze

    Joined:
    Sep 20, 2014
    Posts:
    1
  32. Mangiarotti

    Mangiarotti

    Joined:
    Jan 8, 2016
    Posts:
    1
    You're an HERO elektronische!
    I confirm this works just fine and using lists instead of arrays brings only advantages to me!

    This is how the official unity documentation should look like:

    JsonUtility

    class in UnityEngine

    Other Versions


    Description
    Utility functions for working with JSON data.
    YO FOLKS, arrays DO NOT work with this utility!!! Just use Lists and FromJsonOverwrite to store lists of data.


     
  33. halzate93

    halzate93

    Joined:
    Apr 24, 2013
    Posts:
    4
    Absolutely right^

    However, if you do need/want to use arrays and don't want to/can change the response from the server you could just wrap your json array inside an object. Then you can use the Wrapper<T> method discussed before.

    So if you have this:
    Code (JavaScript):
    1. [
    2.     {
    3.         "id": "1",
    4.         "name": "foo"
    5.     },
    6.     {
    7.         "id": "2",
    8.         "name": "bar"
    9.     },
    10.     {
    11.         "id": "3",
    12.         "name": "baz"
    13.     }
    14. ]
    You want to get something like this:
    Code (JavaScript):
    1. {
    2.     "items": [
    3.         {
    4.             "id": "1",
    5.             "name": "foo"
    6.         },
    7.         {
    8.             "id": "2",
    9.             "name": "bar"
    10.         },
    11.         {
    12.             "id": "3",
    13.             "name": "baz"
    14.         }
    15.     ]
    16. }
    Here's my updated JsonHelper.cs https://gist.github.com/halzate93/77e2011123b6af2541074e2a9edd5fc0
    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3.  
    4.     public static class JsonHelper
    5.     {
    6.         public static T[] FromJson<T>(string jsonArray)
    7.         {
    8.             jsonArray = WrapArray (jsonArray);
    9.             return FromJsonWrapped<T> (jsonArray);
    10.         }
    11.  
    12.         public static T[] FromJsonWrapped<T> (string jsonObject)
    13.         {
    14.             Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(jsonObject);
    15.             return wrapper.items;
    16.         }
    17.  
    18.         private static string WrapArray (string jsonArray)
    19.         {
    20.             return "{ \"items\": " + jsonArray + "}";
    21.         }
    22.  
    23.         public static string ToJson<T>(T[] array)
    24.         {
    25.             Wrapper<T> wrapper = new Wrapper<T>();
    26.             wrapper.items = array;
    27.             return JsonUtility.ToJson(wrapper);
    28.         }
    29.  
    30.         public static string ToJson<T>(T[] array, bool prettyPrint)
    31.         {
    32.             Wrapper<T> wrapper = new Wrapper<T>();
    33.             wrapper.items = array;
    34.             return JsonUtility.ToJson(wrapper, prettyPrint);
    35.         }
    36.  
    37.         [Serializable]
    38.         private class Wrapper<T>
    39.         {
    40.             public T[] items;
    41.         }
    42.     }
    43.  
     
  34. Zhindetz

    Zhindetz

    Joined:
    Nov 13, 2014
    Posts:
    2
    Hi all, thank you for sharing the information.
    I use JavaScript, but did not find any useful example of how to use JsonUtility.FromJson in JavaScript.
    In case anyone is looking for how to deserialize (convert) JSON with array in Unity using JavaScript I've made an example:
    Code (JavaScript):
    1. // Unity data classses
    2. public class Ball { // this is required in both cases: single and array
    3.     public var size : float;
    4.     public var color : String;
    5.     public var weight : int;
    6. }
    7.  
    8. public class Balls { // this is required only in case of array
    9.     public var allBalls : Ball[];
    10. }
    11.  
    12. // Get JSON data
    13. var ballJson : String = '{"size":1,"color":"red","weight":2}';
    14.  
    15. // Instantiate data from JSON
    16. var oneBall : Ball = JsonUtility.FromJson.<Ball>(ballJson);
    17.  
    18. // Use the data
    19. Debug.Log('RED BALL:\nCOLOR: '+oneBall.color+'\nSIZE: '+oneBall.size+'\nWEIGHT: '+oneBall.weight);
    20.  
    21. // Get JSON data
    22. var ballsJson : String = '{"allBalls":[{"size":"1f","color":"red","weight":2},{"size":"1.2f","color":"blue","weight":3},{"size":0.9,"color":"green","weight":5}]}';
    23.  
    24. // Instantiate data from JSON with array
    25. var manyBalls : Balls = JsonUtility.FromJson.<Balls>(ballsJson);
    26.  
    27. // Use the data
    28. for (var i = 0; i < manyBalls.allBalls.length; i++) {
    29.     Debug.Log('#'+i+') BALL:\nCOLOR: '+manyBalls.allBalls[i].color+'\nSIZE: '+manyBalls.allBalls[i].size+'\nWEIGHT: '+manyBalls.allBalls[i].weight);
    30. }
    You can use JsonUtility.FromJson(ballJson, Ball) instead of JsonUtility.FromJson.<Ball>(ballJson) if you like.

    Result looks like:
    ScreenShot.PNG
     
    Last edited: Apr 25, 2017
    superpig likes this.