3

I've been building an English language game using the unity engine. I am struggling to get C# to parse JSON.

I've been trying to get JSON to parse for the last few days, unsuccessfully. I've validated the JSON, can debug the jsonString to the console but as soon as jsonUtility gets its hand on the json then I end up with a load of NULL data.

Here is my json:

 {"question": {"questionType": "0", "categoryID": "0", "bonusBool": "FALSE", "answerText": "cake", "questionText": "If something is really easy to do, it\u2019s a piece of \u2026\u2026\u2026 \\n a. pie \\n b. tart \\n c. cake", "ID": "0"}}

Here is my C#:

 [System.Serializable]
 public class QuestionDataAsString
 {

     public string questionText;
     public string answerText;
     public string categoryID;
     public string ID;
     public string questionType;
     public string bonusBool;

 }

 [System.Serializable]
 public class Question{

     public string questionText;
     public string answerText;
     public int categoryID;
     public int ID;
     public int questionType;
     public bool bonusBool;

 }

 public static void LoadQuestion()
     {
         string filePath = Path.Combine(Application.streamingAssetsPath, "questionData.json");
         string dataAsJSON = File.ReadAllText(filePath);
         Debug.Log(dataAsJSON);
         QuestionDataAsString question = JsonUtility.FromJson<QuestionDataAsString>(dataAsJSON);
         Debug.Log(question.questionText);
     }

 public static Question ConvertQuestionDataFromString(QuestionDataAsString stringData)
     {
         Question question = new Question();
         question.questionText = stringData.questionText;
         question.answerText = stringData.answerText;
         question.categoryID = int.Parse(stringData.categoryID);
         question.ID = int.Parse(stringData.ID);
         question.questionType = int.Parse(stringData.questionType);
         question.bonusBool = Boolean.Parse(stringData.bonusBool);
         return question;
     }

When I run LoadQuestion through a splashscreen controller, I can log the json to console as a string. But I get Null objects once I use jsonUtility.

This is the console output:

 {"question": {"questionType": "0", "categoryID": "0", "bonusBool": "FALSE", "answerText": "cake", "questionText": "If something is really easy to do, it\u2019s a piece of \u2026\u2026\u2026 \\n a. pie \\n b. tart \\n c. cake", "ID": "0"}}
 UnityEngine.Debug:Log(Object)
 SaveLoadManager:LoadQuestion() (at Assets/Scripts/SaveLoadManager.cs:91)
 <Start>c__Iterator0:MoveNext() (at Assets/Scripts/SplashController.cs:18)
 UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

 Null
 UnityEngine.Debug:Log(Object)
 SaveLoadManager:LoadQuestion() (at Assets/Scripts/SaveLoadManager.cs:93)
 <Start>c__Iterator0:MoveNext() (at Assets/Scripts/SplashController.cs:18)
 UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

I've searched through the answers here and on unity answers, but have not found any relevant solutions.

Any ideas why fromJson is returning Null for everything?

6
  • 1
    Your JSON doesn't match your C# class structure. Commented Sep 25, 2017 at 15:10
  • Good luck using that JSON Class, being that unity does not Deseralize JSON Below 7 Nested Levels Commented Sep 25, 2017 at 15:24
  • 1
    @johnny5 What's the problem? This is only 2 levels. Commented Sep 25, 2017 at 15:25
  • @DavidG nothing wrong with the current problem, I just mean Good luck using the JSON Deserializer Class because it doesn't serialize beyond 7 levels. Nobody told me this until I already wrote a project dependent on it, afterwards I had to support it, I think Newtsoft JSON, has a portable version which works with unity Commented Sep 25, 2017 at 15:31
  • @DavidG You are right and your solution works great Commented Sep 26, 2017 at 15:32

1 Answer 1

6

Your JSON doesn't match your C# class structure. You need a root level object to hold the question details. Also, you should use properties, not fields. For example:

public class QuestionRoot
{
    public Question Question { get; set; }
}

public class Question
{
    public string questionType { get; set; }
    public string categoryID { get; set; }
    public string bonusBool { get; set; }
    public string answerText { get; set; }
    public string questionText { get; set; }
    public string ID { get; set; }
}

Now you can do this:

var questionRoot = JsonUtility.FromJson<QuestionRoot>(dataAsJSON);
var questionText = questionRoot.question.questionText;

Side note: You should consider following C# common practice for your naming. Properties almost always start with a capital letter:

public string QuestionText { get; set; }
Sign up to request clarification or add additional context in comments.

5 Comments

This might not work in Unity since the engine does not handle properties as well as it should. But the part about the root object is valid.
@ViktorSeifert Hm that's an interesting point (I'm not a Unity user!)
Thank you, I'll try this solution tomorrow! I'm coming from python, this is my first C# project so I don't know all the conventions yet. As Viktor mentioned, I have read many issues with Unity and properties. If you have a spare minute, unity specific issues aside, could you explain the advantage of using properties over fields?
a note on unity - I had a problem which led me here, reverting all my properties to just fields caused the object to load correctly.
Can confirm, changing it back to fields in Unity fixed it for me, and the 'Serializable' attribute Unity recommends is not needed.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.