Прочитайте и проанализируйте файл Json в C #

240

Большую часть двух дней я потратил на то, чтобы «разобраться» с примерами кода и т. Д., Пытаясь прочитать очень большой JSON-файл в массив в c #, чтобы потом можно было разбить его на 2d-массив для обработки.

Проблема, с которой я столкнулся, заключалась в том, что я не мог найти примеров, когда люди делали то, что пытался сделать. Это означало, что я просто немного редактировал код, надеясь на лучшее.

Мне удалось заставить что-то работать, что будет:

  • Читать файл Пропустить заголовки и читать только значения в массив.
  • Поместите определенное количество значений в каждую строку массива. (Чтобы потом можно было разбить пут на 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") нужен поток, а не строка
vg
13
В C # DotNet Core используйте: using (StreamReader r = File.OpenText ("file.json"))
Фред
20
Для тех, кто не любит читать другие ответы, чтобы понять этот: это решение требует пакета Json.net (Newtonsoft.Json)
Tydaeus
1
Так как у вас все StreamReaderравно есть, было бы лучше десериализовать непосредственно из потока, используя, JsonTextReaderкак показано в Сможет ли Json.NET сериализовать / десериализовать в / из потока? , Это r.ReadToEnd()не нужно.
dbc
43

Делать это самостоятельно - ужасная идея. Используйте Json.NET . Это уже решило проблему лучше, чем большинство программистов могли бы, если бы им давали месяцы подряд над ней работать. Что касается ваших конкретных потребностей, разбора на массивы и тому подобное, проверьте документацию , особенно на JsonTextReader. По сути, Json.NET обрабатывает массивы JSON изначально и будет разбирать их на строки, целые или любые другие типы без запроса от вас. Вот прямая ссылка на базовое использование кода как для читателя, так и для писателя, так что вы можете открыть его в свободном окне, пока вы учитесь работать с этим.

Это к лучшему: будьте ленивы на этот раз и используйте библиотеку, чтобы решить эту распространенную проблему навсегда.

tmesser
источник
1
Я использую Json.net, но я не понимаю, как это работает правильно. когда я читаю информацию с помощью JsonTextReader в текстовое поле, я получаю каждый бит данных, а также заголовки и т. д. Я просто хочу, чтобы в заголовках были пустые поля. Я попытался прочитать документацию по Json.NET, но не нашел, что она объясняет все достаточно для того, чтобы я мог использовать ее так, как мне хотелось бы
Крис Девайн,
@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 - я ненавижу отключать это.

SteveCinq
источник
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

kuzdu
источник
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 и т. Д.

Шайлеш Гавате
источник
3

Это также можно сделать следующим образом:

JObject data = JObject.Parse(File.ReadAllText(MyFilePath));
Адрита Шарма
источник