Why is JSON not saving my Class?

I need to save a List of a class i made. The class is called HeroCard, so naturally i’ll just go with heroCards for my List. I’ll be saving…err, attempting to save this (preferably only this) to a JSON file. At present I have [Serializable] at the top of both my HeroCollection script (where i save it) and HeroCard…well, just above the class declaration.

This is from HeroCollection:

private void LoadHeroesFromJsonFile() {

         // if file exist, read and load to heroCards
         if (File.Exists(path))
         {
             var inputString = File.ReadAllText(path);
             JsonUtility.FromJsonOverwrite(inputString, heroCards);
             
             if(heroCards.Count < 5)
             {
                 Debug.Log("Hero Cards weren't saved!");
                 CreateNewSave();
             }
         }
         else 
         {
             FileInfo file = new FileInfo(path);
             file.Directory.Create();
             CreateNewSave();
             
         }
         Debug.Log("Number of Hero Cards: " + heroCards.Count);
 
     }
 
     private void CreateNewSave()
     {
         for (int i = 0; i < 5; i++)
         {
             HeroCard hc = new HeroCard(1, 0, 1, firstHeroAssets*);*

hc.PopulateInfo();
heroCards.Add(hc);
}

SaveHeroesToJsonFile();
}
…What am I missing here? What is loaded is an empty HeroCard List and it Logs “Hero Cards weren’t saved!”

As others have already mentioned in the comments above, Unity’s JsonUtility does not support an array as the root element. The root element has to be an object. So just use a serializable wrapper class that holds your List of HeroCards

[System.Serializable]
public class Data
{
    public List<HeroCard> cards;
}

So you should serialize / deserialize this class instead. So your json text would look something like this:

{
    "data": [
        {
            Your hero card fields
        },
        {
            Your hero card fields
        }
    ]
}

I’m dumb. After fiddling with having several Lists containing each bit of info, i ran into a wall concerning my method of Loadiing. It relied on everything being in order and if something was removed from one, I’d have to remove the same index from each of the rest. The wall came from the way I load the saved Team by their IDs. Long story short, I went back to my research and found a detail I thought i’d missed, but i hadn’t. However, it did lead me to the culprit.

I was creating a new List of HeroCards instead of saving the one i already had. It opened up the possibilities and I came up with some simple sh-tuff. I found the wonders of Dictionaries even more delightful than I had already. Though you can’t save Dictionaries themselves, you can…can’t remember the word they used…squash (i guess) them down to a List or Array. I’m partial to Lists, myself, and i’ll explain how here in a minute. For the Dictionary I use an integer as the Key, the HeroCard’s ID, and store the HeroCard itself to it.

Anyway, I “convert” this to a List of HeroCards when i save, and save the List in my GameInfo class. Here’s some code. And i won’t accept my own answer unless it gets a few points. Didnt realize accepting closed it to more answers.

void SaveCardData()
    {
        HeroCollection.Instance.heroCards.Clear();
        
        for (int i = 0; i < collectionCap; i++)
        {
            if (HeroCollection.Instance.CollectionHeroCards.ContainsKey(i))
            {
                HeroCollection.Instance.heroCards.Add(HeroCollection.Instance.CollectionHeroCards*);*

Debug.Log(“Added Card with ID " + i + " to saved Hero Cards”);
if (HeroCollection.Instance.heroCards.Count == HeroCollection.Instance.CollectionHeroCards.Count)
{
Debug.Log(“All Hero Cards have been added from the Dictionary. Breaking after " + (i + 1) + " iterations”);
break;
}
}
else Debug.Log("No Hero Card with ID " + i + “was found”);

}

HeroCards = HeroCollection.Instance.heroCards;

}
Can’t do that by the Count of the Dictionary, since there could be cards with IDs higher, so i went with the Collection Cap. Though cards may have higher IDs than the count, a new card will get the lowest missing ID.
Here’s how I save, load, create, and delete the save files:
public void SaveDataToJsonFile()
{
SaveCardData();

string jsonData = JsonUtility.ToJson(this, true);
byte[] jsonByte = Encoding.ASCII.GetBytes(jsonData);

try
{
File.WriteAllBytes(path, jsonByte);
Debug.Log(“Saved Data to: " + path.Replace(”/", “\”));
}
catch (Exception e)
{
Debug.LogWarning(“Failed To Add PlayerInfo Data to: " + path.Replace(”/", “\”));
Debug.LogWarning("Error: " + e.Message);
}
}

private void LoadDataFromJsonFile()
{
// if file exist, read and load to heroCards
if (!Directory.Exists(Path.GetDirectoryName(path)))
{
Directory.CreateDirectory(Path.GetDirectoryName(path));

}

if (!File.Exists(path))
{
Debug.Log(“File does not exist”);
CreateNewSave();
}
else
{
byte[] jsonByte;
try
{
jsonByte = File.ReadAllBytes(path);
Debug.Log(“Loaded Data from: " + path.Replace(”/", “\”));
}
catch (Exception e)
{
Debug.LogWarning(“Failed To Load Data from: " + path.Replace(”/", “\”));
Debug.LogWarning("Error: " + e.Message);
DeleteData();
return;
}

//Convert to json string
string jsonData = Encoding.ASCII.GetString(jsonByte);

JsonUtility.FromJsonOverwrite(jsonData, this);

LoadCardData();
LoadTeamData();

}

}

void LoadCardData()
{
///*
for (int i = 0; i < HeroCards.Count; i++)
{

HeroCard newHeroCard = HeroCards*;*
if(newHeroCard.cardID < 6)
{
newHeroCard.cardLocked = true;
}
HeroCollection.Instance.heroCards.Add(newHeroCard);
HeroCollection.Instance.CollectionHeroCards.Add(newHeroCard.cardID, newHeroCard);
}
//*/
if (HeroCollection.Instance.heroCards.Count < 5)
{
Debug.Log(“Hero Cards weren’t saved!”);
CreateNewSave();
}

}

public void CreateNewSave()
{
for (int i = 0; i < 5; i++)
{
HeroCollection.Instance.SummonNewCard(HeroCollection.Instance.firstHeroAssets*.name);*
}

SaveDataToJsonFile();
}

public void DeleteData()
{
//Exit if Directory or File does not exist
if (!Directory.Exists(Path.GetDirectoryName(path)))
{
Debug.LogWarning(“Directory does not exist”);
return;
}

if (!File.Exists(path))
{
Debug.Log(“File does not exist”);
return;
}

try
{
File.Delete(path);
Debug.Log(“Data deleted from: " + path.Replace(”/", “\”));
}
catch (Exception e)
{
Debug.LogWarning("Failed To Delete Data: " + e.Message);
}

UnityEngine.SceneManagement.SceneManager.LoadScene(0);
}