อ่านและแยกไฟล์ Json ใน C #


239

ฉันใช้เวลาส่วนที่ดีที่สุดของ "faffing" สองวันเกี่ยวกับตัวอย่างโค้ดและอื่น ๆ พยายามอ่านไฟล์ JSON ที่มีขนาดใหญ่มากเป็นอาเรย์ใน c # ดังนั้นฉันจึงสามารถแยกมันออกเป็นอาเรย์ 2d ในภายหลังได้

ปัญหาที่ฉันพบคือฉันไม่สามารถหาตัวอย่างของคนที่ทำในสิ่งที่ฉันพยายามจะทำ นี่หมายความว่าฉันแค่แก้ไขโค้ดให้ดีที่สุด

ฉันจัดการเพื่อให้ได้งานที่จะ:

  • อ่านไฟล์ Miss out header และอ่านค่าในอาเรย์เท่านั้น
  • วางจำนวนที่แน่นอนของค่าในแต่ละบรรทัดของอาร์เรย์ (ดังนั้นฉันสามารถแยกมันใส่ในอาร์เรย์ 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
สิ่งนี้ตอบคำถามของคุณหรือไม่ ฉันจะวิเคราะห์ JSON ด้วย C # ได้อย่างไร
ลิงนอกรีต

คำตอบ:


484

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พันธมิตรโดยไม่ต้องประกาศItemคลาส

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

1
@ChrisDevine jsonฉันหวังว่าคุณไม่ได้ใส่เส้นทางเป็น ต้องเป็นเนื้อหาของไฟล์ของคุณ
LB

4
StreamReader ("file.json") ต้องการ Stream ไม่ใช่ string
vg

13
ใน C # DotNet Core ให้ใช้: using (StreamReader r = File.OpenText ("file.json"))
Fred

20
สำหรับผู้ที่ไม่ชอบอ่านคำตอบอื่น ๆ เพื่อทำความเข้าใจสิ่งนี้: โซลูชันนี้ต้องใช้แพคเกจ Json.net (Newtonsoft.Json)
Tydaeus

1
เนื่องจากคุณมีStreamReaderอยู่แล้วจะเป็นการดีกว่าที่จะทำการดีซีเรียลไลซ์โดยตรงจากสตรีมที่ใช้JsonTextReaderดังที่แสดงในJson.NET สามารถทำให้เป็นอนุกรม / ดีซีเรียลไลซ์เป็น / จากสตรีมได้หรือไม่ . r.ReadToEnd()ไม่จำเป็นต้อง
DBC

43

การทำเช่นนี้เป็นความคิดที่น่ากลัว ใช้Json.NET มันแก้ปัญหาได้ดีกว่าโปรแกรมเมอร์ส่วนใหญ่หากพวกเขาได้รับหลายเดือนเมื่อสิ้นสุดการทำงาน ในฐานะที่เป็นความต้องการของคุณแยกออกเป็นอาร์เรย์และเช่นตรวจสอบเอกสารJsonTextReaderโดยเฉพาะอย่างยิ่งใน โดยทั่วไป Json.NET จะจัดการกับอาร์เรย์ JSON อย่างเป็นธรรมชาติและจะแยกสตริงเหล่านั้นออกเป็นสตริง, ints หรือประเภทใดก็ตามที่เกิดขึ้นโดยไม่ต้องแจ้งให้คุณทราบ นี่คือลิงก์โดยตรงไปยังการใช้งานโค้ดพื้นฐานสำหรับทั้งผู้อ่านและผู้เขียนดังนั้นคุณสามารถเปิดในหน้าต่างว่างขณะที่คุณเรียนรู้ที่จะทำงานกับสิ่งนี้

สิ่งนี้เป็นสิ่งที่ดีที่สุด: อย่าเกียจคร้านคราวนี้และใช้ห้องสมุดเพื่อที่คุณจะได้แก้ปัญหาที่พบบ่อยนี้ได้ตลอดไป


1
ฉันใช้ Json.net แต่ฉันไม่เข้าใจวิธีการทำงานอย่างถูกต้อง เมื่อฉันอ่านข้อมูลโดยใช้ JsonTextReader ในกล่องข้อความฉันได้รับข้อมูลทุกส่วน แต่ยังมีส่วนหัวและอื่น ๆ ฉันต้องการ vaules ที่ส่วนหัว ฉันได้ลองอ่านเอกสาร Json.NET แล้ว แต่ฉันไม่พบมัน exsplains ทุกอย่างเพียงพอสำหรับฉันที่จะใช้ในแบบที่ฉันต้องการ
Chris Devine

@ChrisDevine "ส่วนหัว Json" หรือไม่ คุณหมายถึงกุญแจหรือไม่ อาจจะง่ายกว่านี้ถ้าคุณโพสต์ตัวอย่างสั้น ๆ (~ 10-15 บรรทัด) ของ JSON และชี้ไปที่สิ่งที่คุณกำลังพยายามแยก
tmesser

@ChrisDevine ฉันเพิ่งเพิ่มความคิดเห็นของคุณที่นี่ในคำถามของคุณดังนั้นหากคุณสามารถลบความคิดเห็นด้านบนคนที่ดีกว่านี้ได้
tmesser

@ChrisDevine นอกจากนี้หากคุณสามารถตอบความคิดเห็นที่ฉันมีในคำถามของคุณที่จะน่ากลัว
tmesser

1
@ChrisDevine ใช่ฉันกำลังบอกว่าฉันใส่ไว้ในคำถามของคุณดังนั้นมันไม่จำเป็นอีกต่อไปที่นี่
tmesser

12

ตามวิธีแก้ปัญหาของ @ LB รหัส (พิมพ์ObjectแทนAnonymous) รหัส VB ​​คือ

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

ฉันควรพูดถึงว่านี่เป็นวิธีที่รวดเร็วและมีประโยชน์สำหรับการสร้างเนื้อหาการโทร HTTP ที่ไม่จำเป็นต้องใช้ประเภท และการใช้Objectมากกว่าAnonymousหมายความว่าคุณสามารถรักษาOption Strict Onสภาพแวดล้อมในสภาพแวดล้อม Visual Studio ของคุณ - ฉันเกลียดการปิดการใช้งาน


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

3

สำหรับการค้นหาเส้นทางที่ถูกต้องที่ฉันใช้

   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://stackoverflow.com/a/32071002/4420355


2
วิธีที่ดีกว่าในการค้นหาเส้นทางที่สมบูรณ์โดยไม่คำนึงถึงแอปพลิเคชัน: stackoverflow.com/questions/15653921/get-current-folder-path/…
user3326078

3

สำหรับการแยกวิเคราะห์ JSON ใด ๆ ให้ใช้เว็บไซต์http://json2csharp.com/ (วิธีที่ง่ายที่สุด) ในการแปลง JSON ของคุณเป็นคลาส C # เพื่อเลิกทำการ JSON ของคุณเป็นวัตถุ 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; }        
 }

จากนั้นใช้ JavaScriptSerializer (จาก System.Web.Script.Serialization) ในกรณีที่คุณไม่ต้องการ DLL บุคคลที่สามเช่น newtonsoft

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 เป็นต้น


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.