Newtonsoft Vs System.Text.Json

I am working on a C# .NET Core 3.0 web application that needs to read multiple large json files concurrently so I decided to see what method could give the fastest parse time while using low amount of memory.

Because I am reading so many files at once it is not practical to de-serialize the entire file to memory in one go. I want to open a file stream and then de-serialize an individual object. Carry out operations on that object then dispose of it and move to the next.

I looked at a few libraries but the well established Newtonsoft and the new(ish) System.Text.Json seemed the best contenders.

As input I will be using a 3.7mb products collection in JSON format from my current project. The test code will just read and de-serisalize a product object one by one.

In Newtonsoft the code for this was very simple:

using (FileStream fs = new FileStream(@"E:\Projects\products.json", FileMode.Open, FileAccess.Read))
using (StreamReader sr = new StreamReader(fs))
using (JsonTextReader reader = new JsonTextReader(sr))
{
	while (reader.Read())
	{
		if (reader.TokenType == JsonToken.StartObject)
		{
			var product = JObject.Load(reader).ToObject<Product>();
		}
	}
}

This code uses JsonTextReader to read one record at a time.

With System.Text.Json it was a little harder to get working. There is no method provided for buffering a file stream and reading tokens from it. Luckily I found this thread:

https://stackoverflow.com/a/55429664/657477

Implementing Utf8JsonStreamReader from that thread I ended up with this code:

using (var stream = new FileStream(@"E:\Projects\products.json", FileMode.Open, FileAccess.Read))
using (var jsonStreamReader = new Utf8JsonStreamReader(stream, 32 * 1024))
{
	jsonStreamReader.Read(); // move to array start
	jsonStreamReader.Read(); // move to start of the object

	while (jsonStreamReader.TokenType != JsonTokenType.EndArray)
	{
		// deserialize object
		var obj = jsonStreamReader.Deserialize<Product>();

		// JsonSerializer.Deserialize ends on last token of the object parsed,
		// move to the first token of next object
		jsonStreamReader.Read();
	}
}

Which is faster?

I added some stop watches to the code and this is the console output:

Newtonsoft Ticks: 3906357
Systemn.Text.Json Ticks: 1023668
Systemn.Text.Json is 3.82 times faster!

That is considerably faster. The Utf8JsonStreamReader class is going to need a little tweaking I think for my app but it is a clear cut winner and I will be going with it in my project.

TODO: VS2019 didn’t want to give me any memory performance data (I have vague memory of disabling some stuff to make interface more responsive when debugging so will have to play around to get it working again) so I need to dig into that at a later date but they both seemed fine for my purpose.

Leave a comment

Your email address will not be published. Required fields are marked *