Out Of Memory exception when deserializing with JSON.net – Use Streams instead

Calling an api and deserializing the returned json into a type is something I have to do quite often.

I used to use the following:

//assume client is an instance of HttpClient - this part isn't important
var response = await client.PostAsync(url, content);

//read the response as a string
var responseString = await response.Content.ReadAsStringAsync();

//use json.net to deserialize this into a JObject
var json = (JObject)JsonConvert.DeserializeObject(responseString);

//typically, my json is wrapped up in a 'result' element
var result = JsonConvert.DeserializeObject<IEnumerable<TKeenResult>>(json["result"].ToString());

//now we can deserialize
return JsonConvert.DeserializeObject<IEnumerable<MyResult>>(json["result"].ToString());

From the docs

To minimize memory usage and the number of objects allocated, Json.NET supports serializing and deserializing directly to a stream.

To rectify this, we can instead use Streams

//again, assume client is an instance of HttpClient - this part isn't important
var response = await client.PostAsync(url, content);

using (var stream = await response.Content.ReadAsStreamAsync())
{
    using (var streamReader = new StreamReader(stream))
    {
        using (var reader = new JsonTextReader(streamReader))
        {
            var serializer = new JsonSerializer();

            var responseFromKeen = serializer.Deserialize<TypeContainingMyResult>(reader);
            return responseFromKeen.Result;
        }
    }
}

 

In my example, where the JSON has a nested ‘result’ element, you’ll also need a class to represent this (see `TypeContainingMyResult` above)

public class TypeContainingMyResult
{
	public IEnumerable<MyType> Result {get; set}
}