【问题标题】:How to access and store a particular object from a json file in c#如何在 C# 中从 json 文件访问和存储特定对象
【发布时间】:2020-05-28 08:48:36
【问题描述】:

我正在尝试使用 unity3D 为儿童制作多主题问答游戏,问题和答案存储在 json 文件中。现在我想创建一个名为“科学”和“数学”的对象,并希望将它们各自的问题存储在其中,当我想访问科学时,我可以循环查找并将科学问题存储在我的字符串中,而不是阅读整个json 文件。

这是我的 json 文件。

    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"] 
                  }
                ]   
}

这就是我到目前为止的访问方式

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

    return c1;

课程和需要的可序列化类:

[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;
} 

我已经尝试了很多东西,比如反序列化和 Jobject 资产,但它们似乎都不起作用,而且我在互联网上找到的每个实现都将 json 数据与 c# 代码放在同一个文件中,但我不能这样做我的 json 包含数百行数据。请帮帮我。

【问题讨论】:

标签: c# json unity3d json.net


【解决方案1】:

创建一个课程类,在其中为所有 json 键创建 getter 和 setter 函数,例如:

如果你的 json 文件是这样的:

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

那么课程班级应该是:

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

在您的主课或您可以访问所选课程的任何地方,这里我只使用 0 索引的 json,您也可以遍历整个 json 并找到您想要的课程。

  • StreamReader 读取文件
  • 转成json
  • 根据您的课程反序列化 json
  • 控制台

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

我在 mainClass 文件所在的位置添加了 json 文件,因为 StreamReader 需要绝对路径,因此我为我的 json 文件使用了绝对路径。

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

需要库

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

注意:我创建了一个控制台应用,不确定您的应用类型

【讨论】:

    【解决方案2】:

    如果你想在你的文件中存储多个课程,你需要将它们存储为 json 数组(你可以用问题来做):

    [
       {
          "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"
                ]
             }
          ]
       }
    ]
    

    然后你可以用下一个结构反序列化它们(例如):

    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();
    

    或者尝试使用json path:

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

    jsonString可以通过任何方式获取,例如从文件中读取。

    附言

    有错字“问题”->“问题”

    【讨论】:

      【解决方案3】:

      要序列化和反序列化对象,您必须创建一个可以是 [Serializable] 的 C# 类(在您的情况下应该是 Course 类)。

      首先你的 Json 应该是一个有效的 Json,你可以验证它here

      要序列化和反序列化,您可以使用 JsonUtility 到某个点,因为它不会反序列化锯齿状数组、复杂对象等。我建议使用第三方软件,如 Newtonsoft 或为您的 @ 实现自己的序列化/反序列化方法987654323@.

      编辑:

      您的 JSON 文件应不含“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"] 
                        }
                      ]   
      }
      

      编辑: 对于您的评论,我认为您误解了如何处理文件和变量之间的关系。

      您希望(或至少看起来像这样)每种课程都有一个文件,因此在这种情况下,上面的文本将是您的 Science.json 文件。

      当您存储该信息时,您将执行类似的操作:

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

      因此,正如您所看到的变量名称,您将读取每门课程的每一个 JSON。

      另一种方法是将所有课程存储在同一个 Json 文件中,然后将它们作为课程数组 -> Course[] allCourses

      【讨论】:

      • 兄弟,这正是它之前的写法。但现在我也有一门课程名称“数学”,它有自己的问题。现在我不想在数学测验处于活动状态时将科学问题存储在我的字符串 json 变量中。目前它正在从 json 文件中获取所有内容并将其存储在字符串 json 变量中。
      • @mustafa 我已经更新了答案,告诉我是否有帮助
      【解决方案4】:

      使用Science={...} 定义您的对象是您对对象定义感到困惑的地方。它不是 Science 对象。它是一个Course 对象。

      应该更像

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

      用:

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

      并使用

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

      将其保存为 C# 对象。

      从这里您可以通过quiz.Courses[0].Questions[17] 访问您的课程,或在测验类中编写帮助方法以通过quiz.GetCourse(CourseCategory.Science).Questions[8] 等枚举调用课程。

      我还建议使用Questions 而不是Question_Data。这对对象更友好,并在语义上为您提供帮助。

      作为附加建议,您可以考虑根据课程发送单个 Course 对象,而不是将所有测验转储到单个 JSON 中,使用类似 http://myquizserver.com/quiz.php?course=science 的查询请求。由于您提到了数百行 JSON,您也可以考虑逐个问题地获取数据。

      【讨论】:

      • 您不需要用名称包装它 Quiz 类名对于反序列化并不重要,它也可以是 public class Data 等,只有字段名称必须匹配来自 JSON。有效的 json 根对象不需要名称,可以是 { .... }
      猜你喜欢
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-10
      • 2019-05-27
      • 2017-06-12
      • 2016-08-09
      相关资源
      最近更新 更多