c# - serializar - newtonsoft json serialize vb net
Analizando archivos JSON grandes en.NET (3)
Como ha diagnosticado correctamente en su actualización, el problema es que el JSON tiene un cierre
]
seguido inmediatamente por una apertura
[
para comenzar el siguiente conjunto.
Este formato invalida el JSON cuando se toma como un todo, y es por eso que Json.NET arroja un error.
Afortunadamente, este problema parece surgir con la frecuencia suficiente como para que Json.NET tenga una configuración especial para tratarlo.
Si usa un
JsonTextReader
directamente para leer el JSON, puede establecer el indicador
SupportMultipleContent
en
true
y luego usar un bucle para deserializar cada elemento individualmente.
Esto debería permitirle procesar el JSON no estándar con éxito y de manera eficiente en la memoria, independientemente de cuántas matrices hay o cuántos elementos hay en cada matriz.
using (WebClient client = new WebClient())
using (Stream stream = client.OpenRead(stringUrl))
using (StreamReader streamReader = new StreamReader(stream))
using (JsonTextReader reader = new JsonTextReader(streamReader))
{
reader.SupportMultipleContent = true;
var serializer = new JsonSerializer();
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject)
{
Contact c = serializer.Deserialize<Contact>(reader);
Console.WriteLine(c.FirstName + " " + c.LastName);
}
}
}
Demo completa aquí: https://dotnetfiddle.net/2TQa8p
Hasta ahora he utilizado el método "JsonConvert.Deserialize (json)" de Json.NET que funcionó bastante bien y, para ser sincero, no necesitaba nada más que esto.
Estoy trabajando en una aplicación de fondo (consola) que descarga constantemente el contenido JSON de diferentes URL, luego deserializa el resultado en una lista de objetos .NET.
using (WebClient client = new WebClient())
{
string json = client.DownloadString(stringUrl);
var result = JsonConvert.DeserializeObject<List<Contact>>(json);
}
El simple fragmento de código anterior probablemente no parece perfecto, pero hace el trabajo. Cuando el archivo es grande (15,000 contactos - archivo de 48 MB), JsonConvert.DeserializeObject no es la solución y la línea arroja un tipo de excepción de JsonReaderException.
El contenido JSON descargado es una matriz y así es como se ve una muestra. Contact es una clase contenedor para el objeto JSON deserializado.
[
{
"firstname": "sometext",
"lastname": "sometext"
},
{
"firstname": "sometext",
"lastname": "sometext"
},
{
"firstname": "sometext",
"lastname": "sometext"
},
{
"firstname": "sometext",
"lastname": "sometext"
}
]
Mi suposición inicial es que se queda sin memoria. Solo por curiosidad, traté de analizarlo como JArray, lo que también causó la misma excepción.
He comenzado a sumergirme en la documentación de Json.NET y a leer hilos similares. Como todavía no he logrado producir una solución de trabajo, decidí publicar una pregunta aquí.
ACTUALIZACIÓN: al deserializar línea por línea, recibí el mismo error: "[. Ruta '''', línea 600003, posición 1." Así que descargué dos de ellos y los revisé en Notepad ++. Noté que si la longitud de la matriz es superior a 12,000, después del elemento 12000, se cierra "[" y se inicia otra matriz. En otras palabras, el JSON se ve exactamente así:
[
{
"firstname": "sometext",
"lastname": "sometext"
},
{
"firstname": "sometext",
"lastname": "sometext"
},
{
"firstname": "sometext",
"lastname": "sometext"
},
{
"firstname": "sometext",
"lastname": "sometext"
}
]
[
{
"firstname": "sometext",
"lastname": "sometext"
},
{
"firstname": "sometext",
"lastname": "sometext"
},
{
"firstname": "sometext",
"lastname": "sometext"
},
{
"firstname": "sometext",
"lastname": "sometext"
}
]
He hecho algo similar en Python para el tamaño de archivo de 5 GB. Descargué el archivo en una ubicación temporal y lo leí línea por línea para formar un objeto JSON similar a cómo funciona SAX.
Para C # usando Json.NET, puede descargar el archivo, usar un lector de flujo para leer el archivo, y pasarlo a JsonTextReader y analizarlo a JObject usando
JTokens.ReadFrom(your JSonTextReader object)
.
Json.NET admite la deserialización directamente desde una secuencia.
Aquí hay una manera de deserializar su JSON usando un
StreamReader
lee la cadena JSON de una pieza a la vez en lugar de tener toda la cadena JSON cargada en la memoria.
using (WebClient client = new WebClient())
{
using (StreamReader sr = new StreamReader(client.OpenRead(stringUrl)))
{
using (JsonReader reader = new JsonTextReader(sr))
{
JsonSerializer serializer = new JsonSerializer();
// read the json from a stream
// json size doesn''t matter because only a small piece is read at a time from the HTTP request
IList<Contact> result = serializer.Deserialize<List<Contact>>(reader);
}
}
}
Referencia: Consejos de rendimiento de JSON.NET