c# json.net base64 out-of-memory

c# - Json.Net deserializa el problema de falta de memoria



base64 out-of-memory (3)

Supongo que estás usando 64 bits. Si no, cambia .

Una vez hecho esto, si está utilizando .Net 4.5 o posterior, habilite gcAllowVeryLargeObjects . Permite matrices con entradas int.MaxValue incluso si eso hiciera que el búfer de memoria subyacente fuera de más de 2 GB. Sin embargo, no podrá leer un token JSON único de más de 2 ^ 31 caracteres de longitud, ya que JsonTextReader almacena el contenido completo de cada token en un private char[] _chars; array, y, en .Net, una matriz solo puede contener elementos int.MaxValue .

Obtuve un Json, que contiene, entre otros, un campo de datos que almacena una cadena codificada en base64. Este Json se serializa y se envía a un cliente.

En el lado del cliente, el deserializador newtonsoft json.net se utiliza para recuperar el Json. Sin embargo, si el campo de datos se vuelve grande (~ 400 MB), el deserializador generará una excepción de falta de memoria: las dimensiones de la matriz excedieron el rango admitido . También veo en Task-Manager, que el consumo de memoria realmente crece rápidamente.

¿Alguna idea de por qué es esto? ¿Hay un tamaño máximo para los campos JSON o algo así?

Ejemplo de código (simplificado):

HttpResponseMessage responseTemp = null; responseTemp = client.PostAsJsonAsync(client.BaseAddress, message).Result; string jsonContent = responseTemp.Content.ReadAsStringAsync.Result; result = JsonConvert.DeserializeObject<Result>(jsonContent);

Clase de resultado:

public class Result { public string Message { get; set; } public byte[] Data { get; set; } }

ACTUALIZAR:

Creo que mi problema no es el serializador, sino simplemente tratar de manejar una cadena tan grande en la memoria. En el momento en que leo la cadena en la memoria, el consumo de memoria de la aplicación explota. Cada operación en esa cadena hace lo mismo. Por el momento, creo que tengo que encontrar una forma de trabajar con las transmisiones y dejar de leer todo el material en la memoria a la vez.


Las enormes cadenas de base64 no son un problema como tal, .Net admite tamaños de objetos de alrededor de 2 gb, consulte la respuesta aquí . ¡Por supuesto, eso no significa que puedas almacenar 2gb de información en un objeto!

Sin embargo, tengo la sensación de que es el byte [] ese es el problema.

Si hay demasiados elementos para contener un byte [], no importa si transmite el resultado o incluso lo lee de un archivo en su disco duro.

Entonces, solo para fines de prueba, ¿puede intentar cambiar el tipo de ese de byte [] a cadena o incluso tal vez una lista? No es elegante o tal vez sea aconsejable, pero podría indicar el camino hacia una mejor solución.

Editar:

¿Otro caso de prueba para probar, en lugar de llamar a deserializeObject, intente simplemente guardar esa cadena jsonContent en un archivo y ver qué tan grande es?

Además, ¿por qué lo necesitas en la memoria? ¿Qué tipo de datos es? Me parece que si tienes que procesar esto en la memoria, vas a tener un mal momento: el tamaño del objeto es demasiado grande para el CLR.

Sin embargo, me inspiré un poco, ¿qué tal probar un deserializador diferente? Quizás RestSharp o puede usar HttpClient.ReadAsAsync<T> . Es posible que sea NewtonSoft en sí el que tenga un problema, especialmente si el tamaño del contenido es de alrededor de 400mb.


Leer una cadena JSON grande con el uso de JsonConvert.DeserializeObject consumirá mucha memoria. Entonces, una de las maneras de superar este problema es crear una instancia de JsonSerializer como se detalla a continuación.

using (StreamReader r = new StreamReader(filePath)) { using (JsonReader reader = new JsonTextReader(r)) { JsonSerializer serializer = new JsonSerializer(); T lstObjects = serializer.Deserialize<T>(reader); } }

Aquí filePath : - es su archivo Json actual y T : - es su objeto de tipo genérico.