JSON is easy to work with and has become the standard data format for virtually everything. Although originally derived from the JavaScript scripting language, JSON is now a language-independent data format and code for parsing and generating JSON data is readily available in many programming languages.
At Stackify, we use JSON extensively for REST APIs, serializing messages to queues, and much more. We have compiled a list of some common JSON performance tips. While we use .NET for most of our services, most of these tips apply to other programming languages as well.
In ASP.NET the most popular JSON library is Json.NET (Newtonsoft). But ServiceStack, FastJsonParser (System.Text.Json) and even the built in DataContractJavascriptSerializer may be faster or provide specific features you may need depending on the scenario.
This is based on my own testing and I encourage you to do the same. If you do a lot of parsing and really care about performance, FastJsonParser is a lot faster than anything else I have tried. I highly recommend it. Here are my results from doing some simple benchmarks from a test app (View on GitHub).
Fastest serializer: ServiceStack
Fastest parser: FastJsonParser
Overall most features and flexibility: Json.NET
I haven’t tested it myself but I have also heard good things about Jil which is designed entirely for speed by StackExchange’s team.
Most JSON parsing libraries can read straight from a stream instead of a string. This is a little more efficient and preferred where possible.
Since JSON is just simple text, you can expect to get up to 90% compression. So use gzip wherever possible when communicating with your web services.
This may seem obvious, but it necessarily isn’t. For web apps that receive JSON and simply write it to a queue, database, or other storage, try not to ever parse the JSON if you can. When using something like ASP.NET Web API, don’t define your methods expecting specific classes as incoming data and instead read the post body so ASP.NET never parses the JSON.
For Stackify’s services we use header values for authentication, so in some scenarios, we never even need to analyze the body of the message. We can just queue it and let our background services do further validation of the data later.
[HttpPost] public async Task MyMethod() // no method parameters here! { //Read raw json as a string from the body of the HTTP post, and don’t parse it string results = await Request.Content.ReadAsStringAsync(); //Then write the data as a string to a queue or somewhere }
In some use cases, you may receive a large object array that you have to break up into smaller pieces. For example, at Stackify as part of our error & log management tool, we can receive some large JSON messages of log statements. We queue the log messages as they come in and there is a maximum message size for the queue. In the first version of our code, we were looping through the array and kept serializing one log messages at a time because the final output could only be up to a certain size to queue. We were able to do some optimization of this logic and it made a pretty significant difference in server CPU usage.
If at all possible, make sure you have a class that matches the JSON structure you are working with. Parsing generic JSON to a JSON.net JObject or generic dictionaries with FastJson is slower (~20%) than reading that data in to a defined class type. This is likely because a lot more meta data is tracked with the generic Json.NET’s JObject, JArray, JValue objects.
Newtonsoft.Json.JsonConvert.DeserializeObject<List<MyType>(jsonData); //faster with typed object Newtonsoft.Json.JsonConvert.DeserializeObject(jsonData); //slower with generic JObject result
By default Web API uses Json.NET. If you want to use a different one you can override it by making your own MediaTypeFormatter. In some scenarios you may also want to configure various special settings as well.
Learn how to use an alternate JSON serializer here.
Find info about Web API serialization settings here.
Check your JSON library settings to see how you can ignore specific fields, omit null values, etc. Most .NET libraries will use DataContract/DataMember attributes and settings.
Get Json.Net docs on the subject here.
Most libraries enable you to specify attributes on your classes to override the names of the fields as they are being serialized. This can allow you to make your field names much smaller when serialized but more human readable in your code. Using smaller field names can give you a 5-10% parsing performance boost and of course slightly smaller data packets being passed around.
Most libraries will honor DataMember attributes.
[DataContract] public class Monitor { [DataMember(Name = "id")] public int MonitorID { get; set; } }
Some libraries, like Json.Net and ServiceStack have the ability to let you tailor the serialization and parsing as it occurs. They basically work like a tokenizer and read or write through the JSON one segment at a time. Depending on your use case it could be slower or faster to do this.
I experimented with using Json.Net and a JsonTextReader to improve JSON performance but found that it still didn’t come anywhere close to being as fast as the much easier to use FastJsonParser. This finding was pretty amazing to me.
JSON isn’t the solution for everything. XML has gone out of favor as JSON has become the standard, but depending on your use case, it might still be a good fit for you, especially if you want to enforce a strong schema. Another option is BSON or MessagePack, which are types of binary-based object serialization. The only big downfall is they aren’t human readable or editable like JSON.
Here’s a good article about configuring Web API to support JSON, XML, and different XML settings:
For basic testing, you can use Visual Studio’s built in performance analyzer with a simple console app. Grab a good sample of your JSON and do various serialize/deserialize tests tens of thousands of times in a loop and watch how long it takes, CPU, and memory usage.
View my benchmarking app on GitHub
To measure real world impact of Stackify’s common JSON performance tips, you will want to track server CPU and page load times to compare before and after. You can use Retrace from Stackify to do this.
If you would like to be a guest contributor to the Stackify blog please reach out to [email protected]