Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Json save empty, even though class serializable?

Discussion in 'Scripting' started by IuliusCaesar, Feb 5, 2020.

  1. IuliusCaesar

    IuliusCaesar

    Joined:
    Aug 31, 2019
    Posts:
    7
    Dear Community,

    I am trying to save the stats of enemies in a Json file, using a serializable, simple class:

    Code (CSharp):
    1. [Serializable]
    2. public class SaveStatsOfEnemy
    3. {
    4.     public string enemyName_s;
    5.     public int maxHealth_s;
    6.     public int health_s;
    7.     public int maxArmor_s;
    8.     public int armor_s;
    9.     public int maxShields_s;
    10.     public int shields_s;
    11.     public int maxDodge_s;
    12.     public int dodge_s;
    13.     public Statics.enemyTypes enemyType_s;
    14.  
    15.    
    16. }
    In the SaveSystem class, I've written the following code to save a list of these classes in Json:

    Code (CSharp):
    1.  private void SaveEnemiesToFile()
    2.     {
    3.         // fields for save and load functions
    4.         string savePath = Application.persistentDataPath + "/savegame/" + "enemiesSave.sav";
    5.         string saveDir = Application.persistentDataPath + "/savegame/";
    6.  
    7.         saveStatsListOfEnemies = new List<SaveStatsOfEnemy>();
    8.  
    9.         List<GameObject> enemyGameObjects = new List<GameObject>();
    10.  
    11.         foreach (GameObject obj in GameObject.FindGameObjectsWithTag("Enemy"))
    12.         {
    13.             enemyGameObjects.Add(obj);
    14.         }
    15.  
    16.         foreach (GameObject enemy in enemyGameObjects)
    17.         {
    18.             saveStatsListOfEnemies.Add(enemy.GetComponent<EnemyStatsScript>().ReturnSaveStats());
    19.         }
    20.  
    21.         //check if directory doesn't exit
    22.         if (!Directory.Exists(saveDir))
    23.         {
    24.             //if it doesn't, create it
    25.             Directory.CreateDirectory(saveDir);
    26.  
    27.         }
    28.  
    29.         //This is where the error lies
    30.         string jsonSave = JsonUtility.ToJson(saveStatsListOfEnemies);
    31.  
    32.         //write the file
    33.         File.WriteAllText(savePath, jsonSave);
    34.         Debug.Log(jsonSave);
    35.     }
    When reading out the saveStatsListOfEnemies, I do get the desired data, but the Json itself only cotains "{}".
    Please help if you can spot the error as I'm still pretty new to Json.

    Have many thanks!

    Yours,

    Caesar
     
  2. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,835
    Unity's built-in JSON serializer has some bizarre limitations. IIRC one of them is that it doesn't allow the root structure being serialized to be a list/array. (It can cope with arrays inside of some other object, but not as the root.)

    Instead of serializing a List<SaveStatsOfEnemy>, you could serialize a custom data type that contains a List<SaveStatsOfEnemy>; e.g.
    Code (CSharp):
    1. [Serializable]
    2. public class ListOfSaveStatsOfEnemies
    3. {
    4.     public List<SaveStatsOfEnemy> data;
    5. }

    Alternately, you can switch to a more robust JSON serializer. I believe the Newtonsoft one is popular.
     
    snailcat221 likes this.
  3. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,748
    I haven't found it to be able to use arrays, lists, or Dictionaries inside classes either? Maybe it was only some of those things and I'm misremembering. In any case, yeah, there are other JSON plugins that have much more complete functionality.

    I'd also add LitJson as an option, to me it seems to more easily drop in seamlessly to existing projects. AFAIK the one major advantage Newtonsoft's JSON plugin has is that it can store the class name with the data, which makes it possible to save polymorphic data/inherited classes, while LitJson always just stores data as the declared type.
     
  4. IuliusCaesar

    IuliusCaesar

    Joined:
    Aug 31, 2019
    Posts:
    7
    Thanks a lot, guys!
    I'll be trying out the alternative serializers. I'm really somewhat bamboozled at the built-in serializer's limitations.
     
  5. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,835
    Not sure about dictionaries, but arrays and lists inside of classes are definitely supported. Remember, this is the same serializer used for the Unity inspector, so any public variable that shows up in the default inspector window is something that must be supported.
     
  6. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,748
    Hm, I guess so.

    Speaking of which, I also really wish the Unity inspector serializer supported Dictionary. The number of intermediate arrays I've had to make....
     
  7. RageByte

    RageByte

    Joined:
    Jul 2, 2017
    Posts:
    33
    I thought you had to use properties with JSON?

    Try this on all your fields (turning them into properties) for example:
    public string enemyName_s { get; set; }
     
    Last edited: Feb 6, 2020
  8. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,315
    The JSONUtility class has the same limitations as the built-in Unity serializer does, meaning that it does not support the serialization of properties. Only fields can be serialized by JSONUtility.

    Correct -- lists and arrays are handled specially in the serializer, and can only be serialized as an element of a parent non-array object. The serializer can only handle objects that subclass UnityEngine.Object, built-in structs like Vector3, and classes and structs that are marked Serializable. Lists and arrays fall into none of these categories, and are effectively treated as an edge case by the serializer, not as just another POCO.
     
    Last edited: Feb 6, 2020
  9. RageByte

    RageByte

    Joined:
    Jul 2, 2017
    Posts:
    33
    Bottom line is just do some testing and give the right answer...

    People use C# as a scripting language with Unity and also use C# in Visual Studio 20XX so you have to differentiate. There are differences for sure.