Serializing and deserializing JSON objects are an important part of all software engineer routines. In this article, we will learn different techniques about how to deserialize a complex JSON object in C# and check, with a performance benchmark, which is the fastest technique.
That said, let’s start.
Preparing Environment
Let’s take a look at a complex JSON object that we are going to use in this article:
{ "id": "854e469f-76ec-4036-b10e-2305d5063cc4", "name": "Microsoft", "cofounders": [{ "id": "0d61b68c-f05e-4e6c-822d-6769578f241c", "name": "Bill Gates" }, { "id": "3ef95ce8-7302-470c-afc2-f59d2a3cb2df", "name": "Paul Allen" }], "employees": [{ "id": "6416b2c8-9f8f-4a8e-9f74-ce919ee08a2f", "fullName": "Jane Doe", "anualSalary": 150000, "position": { "id": "b57fe795-0fbf-4da8-bab8-c6a2ba4e709d", "description": "Engineer Manager" }, "benefits": [{ "id": "e3257cb7-0984-42c1-b432-d640dfb0a029", "additional": 3000, "description": "Additional Bonus" }, { "id": "7cda860a-695b-4aac-956a-fb7245c75ef3", "additional": 2500, "description": "Paid Vacation" }] } ... ] }
You can check the full JSON object at this link.
Now, let’s define the POCO (Plain Old CLR Object) classes we are going to use to deserialize this JSON complex object.
Company:
public class Company { public string? Id { get; set; } public string? Name { get; set; } public List<Cofounder>? Cofounders { get; set; } public List<Employee>? Employees { get; set; } }
Cofounder:
public class Cofounder { public string? Id { get; set; } public string? Name { get; set; } }
Employee:
public class Employee { public string? Id { get; set; } public string? FullName { get; set; } public int AnualSalary { get; set; } public Position? Position { get; set; } public List<Benefit>? Benefits { get; set; } }
Position:
public class Position { public string? Id { get; set; } public string? Description { get; set; } }
Benefit:
public class Benefit { public string? Id { get; set; } public int Additional { get; set; } public string? Description { get; set; } }
Now that we have our environment ready, let’s begin deserializing JSON.
Using System.Text.Json To Deserialize a Complex JSON
Our project is using .NET 6.0. That said, we don’t need to install any package to use the System.Text.Json
library. However, it is good to mention that, if we are using any framework earlier than .NET Core 3.0, it is necessary to install this library using the Install-Package System.Text.Json
command in the package manager console.
There’s no secret to deserialize a JSON object. The System.Text.Json
library provides us with a static class JsonSerializer
to help us with this task.
Let’s create a new method to see how we can deserialize a JSON:
private Company? DeserializeUsingGenericSystemTextJson(string json) { var company = JsonSerializer.Deserialize<Company>(json, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); return company; }
As an input parameter, our method receives a JSON string. After the deserialization, it returns a nullable Company
with all the data.
Inside this method, we create a company
variable that is going to receive our deserialized object. Then we call the Deserialize
method from the JsonSerializer
static class and voilà. We have our variable ready to return.
The Deserialize
method receives two parameters, the first represents the JSON object we want to deserialize. The second parameter is optional but recommended. It represents the settings we want to use to deserialize the JSON:
new JsonSerializerOptions() { PropertyNameCaseInsensitive = true }
With the (PropertyNameCaseInsensitive
) property, we inform the deserializer class not to distinguish lower- and uppercase, otherwise, it will assign null
to the mismatch properties.
If we don’t want to use the generic deserialize, the JsonSerializer
class provides us with the same method with another parameter:
var company = (Company?)JsonSerializer.Deserialize(json, typeof(Company), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
Note that we add a new parameter after the JSON. It represents the type we want to deserialize. Besides that, it is necessary to cast the result to the type we want. Without the cast, we are going to have a nullable object instead of the POCO class we defined earlier.
Using Newtonsoft.Json to Deserialize a Complex Json
When we are using a framework version earlier than .NET 3.0, it is recommended to use Newtonsoft.Json to serialize and deserialize objects.
To use this library, we have to run the Install-Package Newtonsoft.Json
command in the package manager console.
Once the installation is complete, let’s add the Newtonsoft.Json
namespace:
using Newtonsoft.Json;
Then, let’s create the method to deserialize the JSON using this library:
private Company? DeserializeUsingNewtonSoftJson(string json) { var company = JsonConvert.DeserializeObject<Company>(json); return company; }
Different from the System.Text.Json
library, this time we are going to use a static class JsonConvert
and the DeserializeObject
generic method. Also, we don’t need to use the second parameter, becauseNewtonsoft.Json
is case insensitive by default.
Anyway, this method gives us another overload. It allows us to pass, as the second parameter, a JsonSerializerSettings
instance.
With JsonSerializerSettings
we can set the culture we want to use when deserializing the JSON object. We can set the DateTime
format and many other settings.
We can check the full list at the Json.net documentation.
Benchmark Comparison
To define which is the fastest way to deserialize a complex JSON object, we are going to run a benchmark comparing the three ways we described in this article.
Let’s create a method to read a very big JSON file we have generated:
private string ReadJsonFile() { using StreamReader reader = new(@$"{AppContext.BaseDirectory}\JsonFiles\VeryBigJson.json"); return reader.ReadToEnd(); }
This JSON object contains a single company with one hundred cofounders and, fifty thousand employees. For each employee, we have ten benefits. The total file size is 35.2 MB. Since it is too big, you would have to download it from GitHub if you want to inspect it.
After running the benchmark we can inspect the result:
| Method | Mean | Error | StdDev | |-------------------------------------- |---------:|---------:|---------:| | DeserializeUsingGenericSystemTextJson | 453.5 ms | 14.43 ms | 40.69 ms | | DeserializeUsingSystemTextJson | 400.9 ms | 7.99 ms | 22.00 ms | | DeserializeUsingGenericNewtonsoftJson | 733.8 ms | 14.37 ms | 25.54 ms |
Analyzing these benchmark results, note that, we have a minimum difference of 53ms between the methods that are using System.Text.Json
library. It implies that the generic approach is a tiny slower than when we are not using generic.
On the other hand, when we look at the third method, which uses the NewtonsoftJson
library, the difference is around 330 ms slower than the fastest approach.
Taking into account that we are using a very big JSON with a 35MB file size, this difference is not too relevant when we are deserializing a small JSON. Nevertheless, a good practice would be using System.Text.Json
whenever it is possible, once Microsoft is constantly improving this library.
Using Json2Csharp Tip
To make it easier to define the POCO classes in C#, based on a JSON complex object, we can use the Json2Csharp website. There, we can use the JSON to C# converter
option and check the Use Pascal Case
checkbox to convert our JSON object.
Difference Between Simple and Complex Json Objects
There is no big difference between simple and complex JSON objects. It means that a complex JSON object has, in its composition, nested objects and collections. That said, the deserialization instructions are the same, however, our POCO classes are much simpler when we are using a simple JSON Object:
{ "Title": "How to Copy Array Elements to New Array in C#", "LastUpdate": "2022-01-31T00:00:00.000", "Link": "https://code-maze.com/csharp-populate-array-same-value/" }
And let’s see the representative POCO class:
public class Article { public string? Title { get; set; } public DateTime LastUpdate { get; set; } public string? Link { get; set; } }
Conclusion
In this article, we have seen different ways to deserialize a complex JSON object using C#.
We have learned an easy way to define POCO classes using the Json2Csharp website, the main difference between a simple and complex JSON object, some deserialization options, classes, and methods.
After a benchmark comparison, we have seen which library is recommended for each scenario and even if we choose the slower technique, the difference would not be too expressive, taking into account that both libraries are very efficient.
Thank you for this great article. We will aim to change our Json serializer code. Thanks again.
You are most welcome.
If you are using Visual Studio, you can copy the JSON into clipboard, and then use the “Edit > Paste Special > Paste JSON as Classes” to generate the POCO.
I cant see “Edit > Paste Special > Paste JSON as Classes” option in Visual Studio 2022 Enterprise and Professional versions, which version are you refeering?
As far as I’ve seen: VS 2019 and 2022, any edition (even Community)
Some text has to be copied in the clipboard previously so that the option appears.
You have to have json or xml string in your clipboard in order to see it