Search code examples
c#jsonunity-game-enginevuforia

Get JSON Data in Unity (2D Array)


I am very new to Unity and C#. I am trying to load a JSON-string to Unity and everything works as expected, but when i want to load a 2D-Array it doesn't work at all.

I have either this...

{
    "status": 0, 
    "email": "exmpl@u", 
    "questions": [
        {
            "A": "Faro", 
            "C": "Oporto", 
            "B": "Lisbon", 
            "D": "Coimbra", 
            "question": "Which is the capital of Portugal?", 
            "your_answer": "", 
            "points": 10, 
            "correct_answer": "B"
        }, 
        {
            "A": "Seville", 
            "C": "Madrid", 
            "B": "Barcelona", 
            "D": "C\u00e1ceres", 
            "question": "Which is the capital of Spain?", 
            "your_answer": "", 
            "points": 15, 
            "correct_answer": "C"
        }, 
        {
            "A": "Gigon", 
            "C": "Cannes", 
            "B": "Marselle", 
            "D": "Paris", 
            "question": "Which is the capital of France?", 
            "your_answer": "", 
            "points": 20, 
            "correct_answer": "D"
        }
    ]
}

...or this string

{
    "status": 0, 
    "email": "exmpl@u", 
    "questions": [
        {
            "A": "Marcelo Rebelo de Sousa", 
            "C": "M\u00e1rio Soares", 
            "B": "Anibal Cavaco Silva", 
            "D": "Jorge Sampaio", 
            "question": "Which is the president of Portugal?",
            "your_answer": "", 
            "points": 10, 
            "correct_answer": "A"
        }, 
        {
            "A": "Fran\u00e7ois Miterrand", 
            "C": "Jacques Chirac", 
            "B": "Emmanuel Macron", 
            "D": "Nicolas Sarkozy", 
            "question": "Which is the president of France?", 
            "your_answer": "", 
            "points": 15, 
            "correct_answer": "B"
        }
    ]
}

i created a class QuizData for saving all the objects in it, looking like this

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

namespace QuizDataManager
{
    public class QuizData
    {
        public int status;
        public string email;
        public string[] questions;
    }
}

i can access the variables status and email easily myQuizDataObject.status or myQuizDataObject.email but i don't get anything with myQuizDataObject.questions[0] or something similar.

How do i do that?


Solution

  • We don't see how exactly you parse that JSON string into the QuizData instance but I'ld assume you are using the JsonUtility.

    Your c# data structure does not represent the structure you get. A cool tool for simply generate a c# layout of existing Json string is json2csharp. Only for Unity make sure to remove all the added {get; set;} which makes properties instead of fields which are not (de)serialized using the JsonUtility.

    It would be something like

    [Serializable]
    public class QuizData
    {
        public int status;
        public string email;
        public Question[] questions;
    }
    
    [Serializable]
    public class Question
    {
        public string A;
        public string C;
        public string B;
        public string D;
    
        public string question;
        public string your_amswer;
        public int points;
        public string correct_answer;
    }
    

    Then you would simply access e.g.

    var myQuizDataObject = JsonUtility.FromJson<QuizData>(theJsonString);
    
    var firstQuestion = myQuizDataObject.questions[0].question;
    var answerA = myQuizDataObject.questions[0].A;
    ...
    

    Depending on your needs instead of string you could also have a proper enum for correct_answer and your_answer like

    public enum AnswerOption
    {
        None,
        A,
        B,
        C,
        D
    }
    
    [Serializable]
    public class Question
    {
        public string A;
        public string C;
        public string B;
        public string D;
    
        public string question;
        public AnswerOption your_amswer;
        public int points;
        public AnswerOption correct_answer;
    }
    

    and could even auto-fill a dictionary with it as also suggested in the other answer e.g. implementing the ISerializationCallbackReceiver interface

    [Serializable]
    public class Question : ISerializationCallbackReceiver
    {
        public readonly Dictionary<AnswerOption, string>() answers;
    
        public string A;
        public string C;
        public string B;
        public string D;
    
        public string question;
        public AnswerOption your_amswer;
        public int points;
        public AnswerOption correct_answer;
    
        public void OnBeforeSerialize()
        {
            // do nothing but required by the interface
        }
    
        public void OnAfterDeserialize()
        {
            answers = new Dictionary<AnswerOption, string>(4);
    
            _myDictionary.Add(AnswerOption.A, A);
            _myDictionary.Add(AnswerOption.B, B);
            _myDictionary.Add(AnswerOption.C, C);
            _myDictionary.Add(AnswerOption.D, D);
        }
    }