Leer y analizar un archivo Json en C #

240

He pasado la mayor parte de dos días "jugando" con muestras de código, etc., tratando de leer un archivo JSON muy grande en una matriz en C # para luego poder dividirlo en una matriz 2D para procesarlo.

El problema que tenía era que no podía encontrar ningún ejemplo de personas que hicieran lo que estaba tratando de hacer. Esto significaba que solo estaba editando código un poco esperando lo mejor.

He logrado hacer que algo funcione que:

  • Leer el archivo Se pierden los encabezados y solo se leen los valores en la matriz.
  • Coloque una cierta cantidad de valores en cada línea de una matriz. (Entonces podría dividirlo y ponerlo en una matriz 2d)

Esto se hizo con el código a continuación, pero bloquea el programa después de ingresar algunas líneas en la matriz. Esto podría tener que ver con el tamaño del archivo.

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

Un fragmento del JSON con el que estoy trabajando es:

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

Necesito los valores de este JSON. Por ejemplo, necesito "3.54", pero no quisiera que imprima el "vcc".

Espero que alguien pueda mostrarme cómo leer un archivo JSON y solo extraer los datos que necesito y ponerlos en una matriz o algo que pueda usar para luego colocarlos en una matriz.

Chris Devine
fuente
1
¿Qué excepción arroja su programa cuando se bloquea?
tmesser
1
¿Responde esto a tu pregunta? ¿Cómo puedo analizar JSON con C #?
Heretic Monkey

Respuestas:

484

¿Qué tal hacer todas las cosas más fáciles con 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;
}

Incluso puede obtener los valores dynamicaliados sin declarar la Itemclase.

dynamic array = JsonConvert.DeserializeObject(json);
foreach(var item in array)
{
    Console.WriteLine("{0} {1}", item.temp, item.vcc);
}
LB
fuente
1
@ ChrisDevine Espero que no hayas puesto el camino como json. Debe ser el contenido de su archivo.
LB
44
StreamReader ("file.json") necesita una secuencia no cadena
vg
13
En C # DotNet Core, use: using (StreamReader r = File.OpenText ("file.json"))
Fred
20
Para la gente a la que no le gusta leer las otras respuestas, entender esta: esta solución requiere el paquete Json.net (Newtonsoft.Json)
Tydaeus
1
Dado que tiene un modo StreamReader, sería mejor deserializar directamente de la transmisión usando JsonTextReadercomo se muestra en ¿Puede Json.NET serializar / deserializar a / de una transmisión? . El r.ReadToEnd()no es necesario.
dbc
43

Hacer esto usted mismo es una idea horrible. Utiliza Json.NET . Ya ha resuelto el problema mejor que la mayoría de los programadores si se les diera meses para trabajar en él. En cuanto a sus necesidades específicas, analizando las matrices y demás, consulte la documentación , especialmente en JsonTextReader. Básicamente, Json.NET maneja las matrices JSON de forma nativa y las analizará en cadenas, entradas o cualquier tipo que sea sin que usted lo solicite. Aquí hay un enlace directo a los usos básicos del código tanto para el lector como para el escritor, para que pueda abrirlo en una ventana libre mientras aprende a trabajar con esto.

Esto es lo mejor: sea flojo esta vez y use una biblioteca para resolver este problema común para siempre.

tmesser
fuente
1
Estoy usando Json.net pero no entiendo cómo funciona correctamente. cuando leo la información usando JsonTextReader en un cuadro de texto, obtengo todos los datos, pero también encabezados, etc. Solo quiero los valores en los encabezados. Traté de leer la documentación de Json.NET pero no encontré que explique todo lo suficiente para que pueda usarla de la manera que me gustaría
Chris Devine
@ChrisDevine "encabezados Json"? ¿Te refieres a las llaves? Quizás esto sería más fácil si publicara un fragmento corto (~ 10-15 líneas) de JSON y señale exactamente lo que está tratando de extraer.
tmesser
@ChrisDevine Acabo de agregar tu comentario aquí a tu pregunta, así que si pudieras eliminar el comentario anterior, sería genial.
tmesser
@ChrisDevine Además, si pudiera responder el comentario que tengo sobre su pregunta, eso también sería increíble.
tmesser
1
@ChrisDevine Sí, estoy diciendo que lo puse en tu pregunta para que ya no sea necesario aquí.
tmesser
12

Basado en la solución de @ LB, el código VB (escrito en Objectlugar de Anonymous) es

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

Debo mencionar que esto es rápido y útil para construir contenido de llamadas HTTP donde no se requiere el tipo. Y usar en Objectlugar de Anonymoussignifica que puede mantener Option Strict Onen su entorno de Visual Studio: odio desactivar eso.

SteveCinq
fuente
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
fuente
3

Para encontrar el camino correcto que estoy 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 utiliza Path.PathSeparator y comprueba si la primera ruta ya tiene un separador al final para que no duplique los separadores. Además, verifica si los elementos de la ruta a combinar tienen caracteres no válidos.

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

kuzdu
fuente
2
Mejor manera de encontrar la ruta absoluta independientemente de la aplicación: stackoverflow.com/questions/15653921/get-current-folder-path/…
user3326078
3

Para cualquiera de los análisis JSON, use el sitio web http://json2csharp.com/ (la forma más fácil) para convertir su JSON en clase C # para deserializar su JSON en 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; }        
 }

Luego use el JavaScriptSerializer (de System.Web.Script.Serialization), en caso de que no desee ninguna DLL de terceros como newtonsoft.

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

Luego puede obtener su objeto con Items.name o Items.Url, etc.

Shailesh Gavathe
fuente
3

Esto también se puede hacer de la siguiente manera:

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