1

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?

derHugo
  • 83,094
  • 9
  • 75
  • 115
lxg95
  • 553
  • 2
  • 8
  • 28
  • Hi, the issue might be because you have a string array defined for questions, but the JSON file contains objects with two strings. Perhaps try making another class called that holds two strings and make an array of that instead? – Milan Karman Jun 12 '19 at 09:53
  • @MilanKarman i don't get the idea of a class with two strings but i made a class with a string for "A","B","C","D", "question" and so on and put the line public Questions[] questions = new Questions[3]; in my QuizData Class and tried to access it with myQuizDataObject.questions[0].A, which still doesn't work. Unity says "NullReferenceException: Object not set to an instance of an Object" – lxg95 Jun 12 '19 at 10:26
  • That sounds like it should work. If you're using Unity's built in JSON parser try using something like https://www.newtonsoft.com/json instead. I've always found Unity's JSON parser to behave strangely – Milan Karman Jun 12 '19 at 10:30

2 Answers2

2

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);
    }
}
derHugo
  • 83,094
  • 9
  • 75
  • 115
1

I think myQuizDataObject.questions[0][A] (Guessing) would get a result, you can see the paring of data like "A": "Faro" which is the Key and the Value. But your data doesn't make much sense. Where did you get it?

It may be an array of Dictionary<string, string>

This seems to be what you need for the questions

{
    "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"
    }]
}
MomasVII
  • 4,641
  • 5
  • 35
  • 52
  • The JSON-data is given by my professor and i can't change it. myQuizDataObject.questions[0][A] is not working.. May i have to change something with my QuizData Class? – lxg95 Jun 12 '19 at 08:22