Leia e analise um arquivo Json em C #

240

Passei a maior parte de dois dias "brincando" com amostras de código e etc., tentando ler um arquivo JSON muito grande em uma matriz em c # para que depois eu possa dividi-la em uma matriz 2D para processamento.

O problema que eu estava tendo era que não conseguia encontrar exemplos de pessoas fazendo o que estava tentando fazer. Isso significava que eu estava apenas editando um pouco o código, esperando o melhor.

Consegui obter algo funcionando que:

  • Leia o arquivo Perca os cabeçalhos e leia apenas os valores na matriz.
  • Coloque uma certa quantidade de valores em cada linha de uma matriz. (Então eu poderia depois dividi-lo e colocá-lo em um array 2D)

Isso foi feito com o código abaixo, mas trava o programa depois de inserir algumas linhas na matriz. Isso pode ter a ver com o tamanho do arquivo.

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

Um trecho do JSON com o qual estou trabalhando é:

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

Eu preciso dos valores deste JSON. Por exemplo, preciso de "3.54", mas não gostaria que ele imprimisse o "vcc".

Espero que alguém possa me mostrar como ler um arquivo JSON e extrair apenas os dados necessários e colocá-los em uma matriz ou algo que eu possa usar para colocar posteriormente em uma matriz.

Chris Devine
fonte
1
Que exceção seu programa lança quando falha?
tmesser
1
Isso responde sua pergunta? Como posso analisar JSON com c #?
Heretic Monkey

Respostas:

484

Que tal facilitar tudo com o 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;
}

Você pode até obter os valores dynamicaliados sem declarar Itemclasse.

dynamic array = JsonConvert.DeserializeObject(json);
foreach(var item in array)
{
    Console.WriteLine("{0} {1}", item.temp, item.vcc);
}
LIBRA
fonte
1
@ ChrisDevine Espero que você não tenha colocado o caminho como json. Deve ser o conteúdo do seu arquivo.
LB
4
StreamReader ("file.json") precisa de um fluxo que não seja string
vg
13
Em C # .Net Core, use: using (StreamReader r = File.OpenText ( "file.json"))
Fred
20
Para as pessoas que não gostam de ler as outras respostas para entender este: esta solução requer que o pacote Json.net (Newtonsoft.Json)
Tydaeus
1
Como você tem uma StreamReadermaneira, seria melhor desserializar diretamente do fluxo usando JsonTextReadercomo mostrado em O Json.NET pode serializar / desserializar para / de um fluxo? . O r.ReadToEnd()não é necessário.
dbc
43

Fazer isso sozinho é uma péssima idéia. Use o Json.NET . Ele já resolveu o problema melhor do que a maioria dos programadores poderia, se recebessem meses a fio para trabalhar nele. Quanto às suas necessidades específicas, analisando matrizes e tal, verifique a documentação , particularmente em JsonTextReader. Basicamente, o Json.NET lida com matrizes JSON nativamente e as analisa em strings, ints ou qualquer que seja o tipo, sem a solicitação da sua parte. Aqui está um link direto para os usos básicos do código, tanto para o leitor quanto para o gravador, para que você possa abri-lo em uma janela sobressalente enquanto aprende a trabalhar com isso.

Isso é o melhor: seja preguiçoso dessa vez e use uma biblioteca para resolver esse problema comum para sempre.

tmesser
fonte
1
Estou usando o Json.net, mas não entendo como funciona corretamente. Quando leio as informações usando JsonTextReader em uma caixa de texto, recebo todos os dados, mas também cabeçalhos, etc. Eu só quero os vaules nos cabeçalhos. Eu tentei ler a documentação Json.NET mas eu não encontrá-lo exsplains tudo o suficiente para eu usá-lo da maneira que eu gostaria
Chris Devine
@ChrisDevine "Json headers"? Você está se referindo às chaves? Talvez isso seja mais fácil se você postou um pequeno trecho (~ 10-15 linhas) de JSON e aponte exatamente para o que está tentando extrair.
tmesser
@ChrisDevine Acabei de adicionar seu comentário aqui à sua pergunta, portanto, se você puder excluir o comentário acima deste, seria ótimo.
tmesser
@ ChrisDevine Além disso, se você pudesse responder ao comentário que tenho sobre sua pergunta, isso também seria incrível.
tmesser
1
@ ChrisDevine Sim, estou dizendo que coloquei na sua pergunta para que não seja mais necessário aqui.
tmesser
12

Com base na solução da @ LB, o código VB (digitado em Objectvez de Anonymous) é

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

Devo mencionar que isso é rápido e útil para a construção de conteúdo de chamada HTTP onde o tipo não é necessário. E usar, em Objectvez de Anonymousmeios, você pode manter Option Strict Onno ambiente do Visual Studio - eu odeio desativar isso.

SteveCinq
fonte
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
        }
Kanad Mehta
fonte
3

Para encontrar o caminho certo que estou usando

   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 usa o Path.PathSeparator e verifica se o primeiro caminho já possui um separador no final para não duplicar os separadores. Além disso, verifica se os elementos do caminho a serem combinados possuem caracteres inválidos.

Consulte https://stackoverflow.com/a/32071002/4420355

kuzdu
fonte
2
Melhor maneira de encontrar o caminho absoluto, independentemente do aplicativo: stackoverflow.com/questions/15653921/get-current-folder-path/…
user3326078
3

Para qualquer análise JSON, use o site http://json2csharp.com/ (maneira mais fácil) para converter seu JSON em classe C # para desserializar seu JSON em objeto 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; }        
 }

Em seguida, use o JavaScriptSerializer (de System.Web.Script.Serialization), caso você não queira nenhuma DLL de terceiros como a newtonsoft.

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

Então você pode obter seu objeto com Items.name ou Items.Url etc.

shailesh gavathe
fonte
3

Isso também pode ser feito da seguinte maneira:

JObject data = JObject.Parse(File.ReadAllText(MyFilePath));
Adrita Sharma
fonte