JSONUtility One works and another similar isn't. What am I missing?

Hi folks,

I have two lots of code which as far as I can see are similar, but only one works.

Working code:

//WheelyThings.cs
[System.Serializable]
public class WheelyThings
{
    // Start is called before the first frame update
    public string Make;
    public string Model;
    public int Wheels;
}


//WheelyList.cs

using System.Collections.Generic;
[System.Serializable]
public class WheelyList
{
    public List<WheelyThings> Vehicles = new List<WheelyThings>();
}

JSONExample.cs

using System.Collections.Generic;
using UnityEngine;

public class JSONExample : MonoBehaviour
{
    public WheelyList VehicleList = new WheelyList();

   void Start()
    {
        TextAsset asset = Resources.Load("Vehicles") as TextAsset;

        if(asset != null)
        {
                        VehicleList = JsonUtility.FromJson<WheelyList>(asset.text);
                       Debug.Log("Count of Vehicles: " + VehicleList.Vehicles.Count);
                        foreach(WheelyThings vehicle in VehicleList.Vehicles)
                        {
                            print(vehicle.Make + " " + vehicle.Model + " " + vehicle.Wheels);
            //                print(vehicle.Model);
              //              print(vehicle.Wheels);
                        }
        }
        else
        {
            print("asset is mull");
        }
    }
}

//WheelyThings.JSON

{
  "Vehicles": [
    {
      "Make": "Toyota",
      "Model": "Camry",
      "Wheels": 4
    },
    {
      "Make": "Yamaha",
      "Model": "YZF-R15",
      "Wheels": 2
    },
    {
      "Make": "Ford",
      "Model": "Ranger",
      "Wheels": 4
    }
  ]
}

This code works. The count is three and the Vehicles are listed. However, the code below does not work:

// Questions.cs
using System.Collections.Generic;

[System.Serializable]
public class Questions
{
    public int ID;
    public string Category;
    public string Question;
    public int PointValue;
    public string CorrAnswer;
    public string altAnswer1;
    public string altAnswer2;
    public string altAnswer3;
}

QuestionList.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class QuestionList {
    public List<Questions> QuestionEntry = new List<Questions>();
}

JSONExample.cs
using System.Collections.Generic;
using UnityEngine;

public class JSONExample : MonoBehaviour
{
    public QuestionList qList = new QuestionList();
   void Start()
    {
        TextAsset asset = Resources.Load("QuizMaster") as TextAsset;

        if(asset != null)
        {
            qList = JsonUtility.FromJson<QuestionList>(asset.text);
            Debug.Log("Count: " + qList.QuestionEntry.Count);
            foreach(Questions questionq in qList.QuestionEntry)
            {
                print(questionq.CorrAnswer);
                print("ooooooo");
            }
        }
        else
        {
            print("asset is mull");
        }
    }
}

// QuizMaster.json

{
  "Questions" : [
    {
      "ID": "1",
      "Category": "Chess",
      "Question": "Who became world chess champion in 1948?",
      "PointValue": 500,
      "CorrAnswer": "Mikhail Botvinnik",
      "altAnswer1": "Robert James Fischer",
      "altAnswer2": "Samuel Reshevsky",
      "altAnswer3": "Tigran Petrosian"
    },
    {
      "ID": "2",
      "Category": "Literature",
      "Question": "Who was not one of the original Musketeers?",
      "PointValue": 100,
      "CorrAnswer": "D'artagnan",
      "altAnswer1": "Athos",
      "altAnswer2": "Porthos",
      "altAnswer3": "Aramis"
    },
    {
      "ID": "3",
      "Category": "Literature",
      "Question": "To begin with Marley was as dead as a doornail, are the opening lines to what novel?",
      "PointValue": 200,
      "CorrAnswer": "A Christmas Carol",
      "altAnswer1": "The Turn of the Screw",
      "altAnswer2": "The Scarlet Pimpernel",
      "altAnswer3": "Howard's End"
    }
  ]
}

The count is 0 and no listing is printed. What am I missing? Any help is much appreciated.

JsonUtility doesn’t handle List or Dictionary. (I’m actually just surprised that your first example seems to work, it really shouldn’t.) Use LitJson instead; similar operation, but much more capable.

1 Like

“JsonUtility doesn’t handle List or Dictionary”

It does serialize list (just like Unity inspector will) if the list is contained in a serialized class, like in @Seaworth code. But it won’t serialize dictionary, unless using ISerializationCallbackReceiver to circumvent dictionary limitation by putting keys and values into lists.

2 Likes

@Seaworth

Your data has to be in very exact format for it to work - you need store a list inside serializable class, then serialize that class. Same goes for reading the json with JsonUtility… your data needs to be in format:

 {
  "questions":
   [
   ]
}

But now in your data, you have “Questions” when it should be the thing contained in container class. I changed the names a bit to make it more easy to understand (for myself mostly):

public class JsonExample : MonoBehaviour
{
    public List<Question> questions;
    public TextAsset asset;

    void Start()
    {
        if(asset != null)
        {
            // json format needed:  {"questions":[]}

            // Get questions container
            var json = JsonUtility.FromJson<QuestionList>(asset.text);

            // Get questions list from container
            questions = json.questions;
        }
    }
}

// container for questions
[System.Serializable]
public class QuestionList
{
    public List<Question> questions = new List<Question>();
}


// question
[System.Serializable]
public class Question
{
    public int ID;
    public string Category;
    public string question;
    public int PointValue;
    public string CorrAnswer;
    public string altAnswer1;
    public string altAnswer2;
    public string altAnswer3;
}

And your JSON has to be changed to match class contents, like I mentioned, for this to work:

{
    "questions": [
        {
            "ID": "1",
            "Category": "Chess",
            "Question": "Who became world chess champion in 1948?",
            "PointValue": 500,
            "CorrAnswer": "Mikhail Botvinnik",
            "altAnswer1": "Robert James Fischer",
            "altAnswer2": "Samuel Reshevsky",
            "altAnswer3": "Tigran Petrosian"
        },
        {
            "ID": "2",
            "Category": "Literature",
            "Question": "Who was not one of the original Musketeers?",
            "PointValue": 100,
            "CorrAnswer": "D'artagnan",
            "altAnswer1": "Athos",
            "altAnswer2": "Porthos",
            "altAnswer3": "Aramis"
        },
        {
            "ID": "3",
            "Category": "Literature",
            "Question": "To begin with Marley was as dead as a doornail, are the opening lines to what novel?",
            "PointValue": 200,
            "CorrAnswer": "A Christmas Carol",
            "altAnswer1": "The Turn of the Screw",
            "altAnswer2": "The Scarlet Pimpernel",
            "altAnswer3": "Howard's End"
        }
    ]
}
1 Like

In your second example, your saved list in your json file is Questions where as the name in the class is QuestionEntry.

Change “Questions” to “QuestionEntry” in the json or rename the list to Questions and it should work.

1 Like

That seems to have worked. I changed QuestionEntry to Questions and voila. Now to check with the full JSON set. Thank you!!