mustafa
mustafa

Reputation: 29

How to access and store a particular object from a json file in c#

I am trying to make a multi-subject quiz game for children using unity3D and questions and answers are stored in a json file. Now i want to create an object named "science" and "maths" and want to store their respective questions in them and when i want to access science i could loop and find and just store the science question in my string instead of reading the whole json file.

here is my json file.

    Science ={
    "CourseName":"Science",
    "No_Of_Ques":4,
    "Ques_Data":[
                  { "Quesion":"which is the biggest planet in the solar system?",
                    "Answer":"jupiter",
                    "options":["mars","earth","venus","jupiter"] 
                  },

                  { "Quesion":"How many planets are there in solar system?",
                    "Answer":"Eight",
                    "options":["Seven","Nine","Five","Eight"] 
                  },

                  { "Quesion":"which is the closest planet to the sun?",
                    "Answer":"mercury",
                    "options":["mars","saturn","venus","mercury"] 
                  },

                  { "Quesion":"How many moons does jupiter have?",
                    "Answer":"12",
                    "options":["5","13","9","12"] 
                  }
                ]   
}

and this is how i have been acessing it so far

path = Application.dataPath + "/QnA.json";
    string json = File.ReadAllText(path);
    Course c1 = JsonUtility.FromJson<Course>(json);

    return c1;

Course and needed serializable Classes:

[Serializable] public class Course 
{ 
    public string CourseName;
    public string No_Of_Ques;
    public QnA[] Ques_Data; 
}

[Serializable]
public class QnA 
{ 
    public string Quesion;
    public string Answer;
    public string[] options;
} 

i have tried so many things like Deserialization and Jobject asset but none of them seem to work and every implementation that i have found on the internet has the json data in the same file as the c# code but i can not do that as my json contains hundreds of lines of data. kindly help me out a little.

Upvotes: 1

Views: 1073

Answers (4)

Guru Stron
Guru Stron

Reputation: 142173

If you want to store multiple courses in your file you will need to store them as json array (as you do with questions):

[
   {
      "CourseName":"Science",
      "No_Of_Ques":1,
      "Ques_Data":[
         {
            "Question":"which is the biggest planet in the solar system?",
            "Answer":"jupiter",
            "options":[
               "mars",
               "jupiter"
            ]
         }
      ]
   },
   {
      "CourseName":"Math",
      "No_Of_Ques":1,
      "Ques_Data":[
         {
            "Question":"2 + 2",
            "Answer":"4",
            "options":[
               "4",
               "0"
            ]
         }
      ]
   }
]

then you can deserialize them with next structure(for example):

public class Course
{
    [JsonProperty("CourseName")]
    public string CourseName { get; set; }
    [JsonProperty("No_Of_Ques")]
    public long NoOfQues { get; set; }
    [JsonProperty("Ques_Data")]
    public QuesDatum[] QuesData { get; set; }
}

public class QuesDatum
{
    [JsonProperty("Question")]
    public string Question{ get; set; }

    [JsonProperty("Answer")]
    public string Answer { get; set; }

    [JsonProperty("options")]
    public string[] Options { get; set; }
}


var courses = JsonConvert.DeserializeObject<List<Course>>(jsonString);
var course = courses.Where(...).FirstOrDefault();

Or try to use json path:

var course = JToken.Parse(jsonString)
    .SelectToken("$[?(@.CourseName == 'Math')]")
    .ToObject<Course>();

As for jsonString you can obtain it in any way, reading from file for example.

P.S.

There was typo "Quesion" -> "Question"

Upvotes: 1

hcurnor
hcurnor

Reputation: 43

Create a course class in which create getter and setter functions for all of your json keys, for example:

if your json file is like that:

[
  {
    "CourseName": "Science",
    "No_Of_Ques": 1,
    ...
  },
  {
    "CourseName": "Math",
    "No_Of_Ques": 1,
    ...
  }
]

then course class should be:

public class Course
    {
        public string CourseName { get; set; }
        public int No_Of_Ques { get; set; }
    }

In your main class or anywhere you can access your selected course, here i am using only 0 index of a json, you can also loop through whole json and find your desirable course.

  • StreamReader to read a file
  • convert it to json
  • Deserialize the json as per your course
  • Console it

        using (StreamReader r = new StreamReader("../../../js.json"))
        {
            string json = r.ReadToEnd();
            List<Course> ro = JsonSerializer.Deserialize<List<Course>>(json);
            Console.WriteLine(ro[0].CourseName);
        }
    

I added json file in the same dire where my mainClass file is, as StreamReader requires an absolute path therefore I used an absoulte path for my json file.

using (StreamReader r = new StreamReader("../../../js.json"))

Require Libs

using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;

Note: I created a console app, not sure your app type

Upvotes: 2

Guney Ozsan
Guney Ozsan

Reputation: 330

Using Science={...} to define your object is where you get confused about object definitions. It is not a Science object. It is a Course object.

It should be more like

{
    "Courses" :
    [
        {
            "CourseName" : "Science",
            ...
        },
        {
            "CourseName" : "Maths",
            ...
        }
    ]
}`.

Wrap it with:

"Quiz" :
{
    "Courses" :
    [
        {
            "CourseName" : "Science",
            ...
        },
        {
            "CourseName" : "Maths",
            ...
        }
    ]
}

and use

[Serializable]
public class Quiz
{
    public Course[] courses;
}

To hold it as a C# object.

From here you can access your courses by quiz.Courses[0].Questions[17] or write helper methods in Quiz class to call courses by enums like quiz.GetCourse(CourseCategory.Science).Questions[8].

I also suggest using Questions instead of Question_Data. That is more object friendly and helps you semantically.

As an additional suggestion, instead of dumping all of the quiz in a single JSON, you may consider sending a single Course object depending on the course, requested using a query like http://myquizserver.com/quiz.php?course=science. Since you mentioned hundreds of lines of JSON, you may also consider getting data question by question.

Upvotes: 0

Lotan
Lotan

Reputation: 4283

To serialize and deserialize objects you have to create a C# class (in your case should be Course class) that can be [Serializable].

First your Json should be a valid one, which it is, you can validate it here.

To serialize and deserialize you can use JsonUtility to certain point, cause it doesn't deserialize jagged arrays, complex objects etc. I recommend to use third party softwares like Newtonsoft or implement your own serialization/deserialization method for your way.

Edit:

Your JSON file should be without the "Science=" part, should look like:

{
    "CourseName":"Science",
    "No_Of_Ques":4,
    "Ques_Data":[
                  { "Quesion":"which is the biggest planet in the solar system?",
                    "Answer":"jupiter",
                    "options":["mars","earth","venus","jupiter"] 
                  },

                  { "Quesion":"How many planets are there in solar system?",
                    "Answer":"Eight",
                    "options":["Seven","Nine","Five","Eight"] 
                  },

                  { "Quesion":"which is the closest planet to the sun?",
                    "Answer":"mercury",
                    "options":["mars","saturn","venus","mercury"] 
                  },

                  { "Quesion":"How many moons does jupiter have?",
                    "Answer":"12",
                    "options":["5","13","9","12"] 
                  }
                ]   
}

Edit: For your comment I think you got a misunderstood of how to handle the relation between files and variables.

You want to have (or at least it seems like this) one file for every type of course, so in this case, the text above will be your Science.json file.

When you store that information, you will do similar of what you do:

path = Application.dataPath + "/QnA.json";
    string json = File.ReadAllText(path);
    Course scienceCourse = JsonUtility.FromJson<Course>(json); //notice the name of the variable!

So as you can see for the variable name, you will read EVERY SINGLE JSON for every course.

The other way to do that, is to store all the courses on the same Json file, and then get them as an ARRAY of Courses -> Course[] allCourses

Upvotes: 1

Related Questions