在C#中读取和解析Json文件

387
如何在C#中将一个非常大的JSON文件读入一个数组中,以便以后进行分割处理?
我已经设法让以下代码工作:
  • 读取文件
  • 跳过标题只读取值到数组中
  • 将一定数量的值放在数组的每一行中(这样我就可以将其拆分并放入2D数组中)
但是它会在将几行输入到数组后使程序崩溃。这可能与文件大小有关。
// If the file extension was a jave file the following 
// load method will be use else it will move on to the 
// next else if statement
if (fileExtension == ".json") 
{
    int count = 0;
    int count2 = 0;
    int inOrOut = 0;
    int nRecords=1; 
    JsonTextReader reader = new JsonTextReader(new StreamReader(txtLoaction.Text));
    string[] rawData = new string[5];
    while (reader.Read())
    {
        if (reader.Value != null)
            if (inOrOut == 1)
            {
                if (count == 6)
                {
                    nRecords++;
                    Array.Resize(ref rawData, nRecords);
                    //textBox1.Text += "\r\n";
                    count = 0;
                }
                rawData[count2] += reader.Value + ","; //+"\r\n"
                inOrOut = 0;
                count++;
                if (count2 == 500)
                {
                    MessageBox.Show(rawData[499]);
                }
            }
            else
            {
                inOrOut = 1;
            }
    } 
}

我正在处理的JSON代码片段如下:

[ 
    { "millis": "1000", 
      "stamp": "1273010254", 
      "datetime": "2010/5/4 21:57:34", 
      "light": "333", 
      "temp": "78.32", 
      "vcc": "3.54" }, 
] 

我需要从这个JSON中获取值。例如,我需要“3.54”,但不希望打印出“vcc”。

如何读取JSON文件并仅提取所需的数据以放入数组?


1
当你的程序崩溃时,它会抛出什么异常? - tmesser
1
这个回答解决了你的问题吗?如何使用C#解析JSON? - Heretic Monkey
这个回答解决了你的问题吗?Json.NET能否将数据序列化/反序列化到/自流中? - Liam
13个回答

689

使用 Json.NET 可以让一切变得更简单,你觉得怎么样?


    public void LoadJson()
    {
        using (StreamReader r = new StreamReader("file.json"))
        {
            string json = r.ReadToEnd();
            List<Item> items = JsonConvert.DeserializeObject<List<Item>>(json);
        }
    }

    public class Item
    {
        public int millis;
        public string stamp;
        public DateTime datetime;
        public string light;
        public float temp;
        public float vcc;
    }

你甚至可以在不声明类的情况下,动态地获得值。

    dynamic array = JsonConvert.DeserializeObject(json);
    foreach(var item in array)
    {
        Console.WriteLine("{0} {1}", item.temp, item.vcc);
    }

3
@ChrisDevine,我希望你没有把路径设置成了 json。它必须是你文件的内容。 - L.B
6
StreamReader("file.json") 需要一个流(Stream)而不是一个字符串(string)。 - v.g.
18
在 C# DotNet Core 中,使用以下代码:using (StreamReader r = File.OpenText("file.json"))来打开名为 "file.json" 的文件。 - Fred
34
对于不想阅读其他回答的人,理解这个答案需要 Json.net 包(Newtonsoft.Json)。 - Tydaeus
2
由于您已经有了StreamReader,最好使用JsonTextReader直接从流中反序列化,如Can Json.NET serialize / deserialize to / from a stream?所示。 r.ReadToEnd()是不必要的。 - dbc
显示剩余7条评论

54

.NET Core的答案

您可以直接使用内置的System.Text.Json而不是第三方的Json.NET。为了促进重用,JSON文件读取功能应该放在自己的类中,并且应该是通用的,而不是硬编码到某个类型(Item)。以下是完整的示例:

using System;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;

namespace Project
{
    class Program
    {
        static async Task Main()
        {
            Item item = await JsonFileReader.ReadAsync<Item>(@"C:\myFile.json");
        }
    }

    public static class JsonFileReader
    {
        public static async Task<T> ReadAsync<T>(string filePath)
        {
            using FileStream stream = File.OpenRead(filePath);
            return await JsonSerializer.DeserializeAsync<T>(stream);
        }
    }

    public class Item
    {
        public int millis;
        public string stamp;
        public DateTime datetime;
        public string light;
        public float temp;
        public float vcc;
    }
}

或者,如果您更喜欢简单/同步的方式:

class Program
{
    static void Main()
    {
        Item item = JsonFileReader.Read<Item>(@"C:\myFile.json");
    }
}

public static class JsonFileReader
{
    public static T Read<T>(string filePath)
    {
        string text = File.ReadAllText(filePath);
        return JsonSerializer.Deserialize<T>(text);
    }
}

我尝试了你的解决方案,但CSC不允许Main()是异步的:错误CS4009:“void或int返回入口点不能是异步的”。 - geriwald
@geriwald 抱歉,async Main 需要返回 Task 而不是 void。我已经更新了它。 - MarredCheese
值得一提的是,这是首次在.NET 5.0中提供。如果您使用的是早期版本,请查看Json.net解决方案。 - JamieB
基于文档页面的版本,我认为该功能从.NET Core 3.0开始就已经可用了。但你指出它一开始并不存在是正确的。 - MarredCheese

49
自己去做这件事是一个糟糕的想法。使用Json.NET,它已经比大多数程序员在几个月内解决此问题更好了。至于您的特定需求,如解析成数组等,请查看文档,特别是关于JsonTextReader的部分。基本上,Json.NET本地处理JSON数组,并将它们解析为字符串、整数或任何类型,而无需提示您。这里是读者和作者的基本代码用法的直接链接,因此当您学习使用它时,可以在备用窗口中打开它。这里
这是最好的方法:这一次懒一点,并使用库来永远解决这个常见问题。

1
我正在使用Json.net,但我不理解它如何正确工作。当我使用JsonTextReader将信息读入文本框时,我得到了所有数据的每一位,但也包括头文件等。我只想要标题中的值。我尝试阅读Json.NET文档,但我没有找到足够详细的说明,以便我按照自己的方式使用它。 - Chris Devine
@ChrisDevine "Json headers"? 你是指键吗?也许如果您发布一个短的(〜10-15行)JSON片段,并指出您要提取的内容,这将更容易些。 - tmesser
@ChrisDevine,我刚刚把你的评论添加到了你的问题中,如果你能删除上面的评论,那就太好了。 - tmesser
@ChrisDevine 如果您能回答我在您的问题上的评论,那也太棒了。 - tmesser
我发布了一小段数据片段,这是我正在尝试恢复的数据。 - Chris Devine
1
@ChrisDevine 是的,我是说我把它放在你的问题中,所以在这里就不再需要了。 - tmesser

33

这也可以用以下方式完成:

JObject data = JObject.Parse(File.ReadAllText(MyFilePath));

这段代码片段在独立运行时无法工作。它是否需要 Newtonsoft? - undefined

19
string jsonFilePath = @"C:\MyFolder\myFile.json";
            
string json = File.ReadAllText(jsonFilePath);
Dictionary<string, object> json_Dictionary = (new JavaScriptSerializer()).Deserialize<Dictionary<string, object>>(json);

foreach (var item in json_Dictionary)
{
    // parse here
}

16

基于 @L.B. 的解决方案,(类型为 Object 而不是 Anonymous)的 VB 代码如下:

Dim oJson As Object = JsonConvert.DeserializeObject(File.ReadAllText(MyFilePath))

我应该提到,这对于构建 HTTP 调用内容非常快捷实用,其中类型不是必需的。而且使用 Object 而不是 Anonymous 意味着您可以在 Visual Studio 环境中保持 Option Strict On - 我讨厌关闭它。


9

对于任何JSON解析,使用网站http://json2csharp.com/(最简单的方式)将您的JSON转换为C#类,以将其反序列化为C#对象。

 public class JSONClass
 {
        public string name { get; set; }
        public string url { get; set; }
        public bool visibility { get; set; }
        public string idField { get; set; }
        public bool defaultEvents { get; set; }
        public string type { get; set; }        
 }

如果您不想使用类似于newtonsoft的第三方DLL,可以使用JavaScriptSerializer(来自System.Web.Script.Serialization)。

using (StreamReader r = new StreamReader("jsonfile.json"))
{
   string json = r.ReadToEnd();
   JavaScriptSerializer jss = new JavaScriptSerializer();
   var Items = jss.Deserialize<JSONClass>(json);
}

然后你可以使用 Items.name 或 Items.Url 等方式获取对象。


9
现在你可以直接在VS中将JSON转换为C#,方法是 编辑 -> 特殊粘贴 -> 以类形式粘贴JSON - Liam

8

我在网上找到了一个非常简单的方法来在C#(或任何其他编程语言)中使用.JSON文件。

前提条件:-

这里是URL -> https://app.quicktype.io/

步骤

1> 访问此URL - https://app.quicktype.io/

2> 将您的JSON文件结构复制并粘贴到左侧边栏中

app.quicktype.io

3> 从选项菜单中选择所需的语言(这里是C#)

4> 复制生成的代码并转到您的项目,创建一个具有相同名称的新.cs文件(这里是“Welcome.cs”)

Welcome.cs

5> 将所有生成的代码粘贴到新创建的类中。

Welcome.cs粘贴的代码

6> 完成了。 :)

访问值的步骤

1> 转到主程序.cs文件或需要访问它的任何位置。

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Access Json values using Keys.>");

        String jsonString = new StreamReader("give <.json> file Path here").ReadToEnd();

        // use below syntax to access JSON file
        var jsonFile = Welcome.FromJson(jsonString);

        string FileName = jsonFile.File;
        long Lvl = jsonFile.Level;
        bool isTrue = jsonFile.CSharp;

        Console.WriteLine(FileName);//JSON
        Console.WriteLine(Lvl);//1
        Console.WriteLine(isTrue);//true
    }
}

5

我正在使用寻找正确路径

   var pathToJson = Path.Combine("my","path","config","default.Business.Area.json");
   var r = new StreamReader(pathToJson);
   var myJson = r.ReadToEnd();

   // my/path/config/default.Business.Area.json 
   [...] do parsing here 

Path.Combine使用Path.PathSeparator,并检查第一个路径是否已经以分隔符结尾,以便不会重复分隔符。另外,它还检查要组合的路径元素是否具有无效字符。

请参见https://dev59.com/-lwY5IYBdhLWcg3w5rWq#32071002


2
无论应用程序如何,找到绝对路径的更好方法: https://dev59.com/QGUo5IYBdhLWcg3w7jIq#23513793 - user3326078

4

有一个比 Json.Net 更快的解析 json 的方法。如果您正在使用 .net core 3.0 或更高版本,则可以使用 System.Text.Json nuget 包进行序列化或反序列化。

您需要添加:

using System.Text.Json

然后你可以将其序列化为:

var jsonStr = JsonSerializer.Serialize(model);

并反序列化为:

var model = JsonSerializer.Deserialize(jsonStr);

1
我认为你的第二点是指序列化。 - Indigo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接