Working with JSON in .NET Core 3

With the introduction of ASP.NET Core 3.0 the default JSON serializer has been changed from Newtonsoft.Json to the native System.Text.Json. In this blog post, we will go over some basic usages of JSON serialization and deserialization. The complete solution can be found in this GitHub repository.


A short intro to the fast built-in JSON support

The new built-in JSON support, System.Text.Json, is high-performance, low allocation, and based on Span<byte>. This is all automatic and built in with .NET Core 3.0. But if your project is targeting to .NET Standard or .NET framework (v4.6.1+), then you need to install the System.Text.Json NuGet package, or you can continue to use Json.NET or other popular JSON libraries.

Even though there were many discussions on the JSON library for .NET Core (link), for most .NET users, it is good news to see a native JSON library. Also, there are several benchmark articles (link1, link2, link3, …) which show that the System.Text.Json namespace holds a better performance in most use cases as compared to other JSON libraries. Microsoft has done an excellent job!

The System.Text.Json namespace provides high-performance, low-allocating, and standards-compliant capabilities to process JavaScript Object Notation (JSON), which includes serializing objects to JSON text and deserializing JSON text to objects, with UTF-8 support built-in. It also provides types to read and write JSON text encoded as UTF-8, and to create an in-memory document object model (DOM) for random access of the JSON elements within a structured view of the data.

System.Text.Json Namespace from Microsoft Docs

A must-read tutorial by Microsoft Docs

Microsoft Docs has a very good how-to article: How to serialize and deserialize JSON in .NET. Even though it is still under construction, this article has covered a lot of use cases of the System.Text.Json namespace.

In the rest of this blog post, I will show some common use cases of JSON serialization and deserialization.


Using JsonSerializer

Let’s consider a model class MyModel which is defined as follows.

gist link

This class contains some properties in common object types in C#. We are going to deserialize a JSON file to a MyModel object instance. The JSON file, “my-model.json”, looks like the following.

gist link

It is straightforward to deserialize a JSON string to a C# model class using the JsonSerializer.Deserialize method under the System.Text.Json namespace. On the other hand, we can use JsonSerializer.Serialize method to serialize a MyModel object instance to JSON string. The following code snippet shows an example.

gist link

Lines 3 to 6 define the JSON serializer options. There are a set of options available (link). Here, two properties in the options are explicitly set. The first one, PropertyNamingPolicy, tells the serializer to use CamelCase to deserialize and serialize, so that a property named “MyProperty” in a C# class will match with a key “myProperty” in the JSON object, and vice versa. The second one, WriteIndented = true, means that the serialized JSON string should use pretty printing with proper indentations. The console output of the code above is like the following screenshot.

The example above is an ideal case; everything works as it should. However, we occasionally need to deal with JSON objects that are not following the naming convention. In this case, we can use a built-in attribute annotation, JsonPropertyName, to map a property in a C# class to a key in a JSON object. The following code snippet shows an example that the Name property is mapped to the “_full_name” key-value pair in the JSON string.

gist link
gist link

There’s another attribute, JsonIgnore, in the above example. This attribute can suppress the annotated property in the serialization process.


Using JsonDocument

Sometimes, we have a large JSON object and we only care about a very small part of it. In this case, we can leverage the JsonDocument in the System.Text.Json namespace.

The JsonDocument provides a mechanism for examining the structural content of a JSON value without automatically instantiating data values. The JsonDocument can parse the JSON value and generate an in-memory document object model (DOM) for random access and enumeration of the JSON elements.

The following code snippet shows an example.

gist link

In this example, we first let JsonDocument parse the JSON string, and get a hold of the RootElement of the JSON value. With the RootElement, we can query the value directly by the key in the JSON object. The type conversion supports most of the primitive types. In addition, we can enumerate a JsonElement. For example, lines 12 to 17 show how to work with an array in JSON and convert it to a List in C#.


That’s all for today. As I only touched some very basic areas of the System.Text.Json namespace, please make sure you have read the official tutorial (link), which includes more examples, explanations and discussions.

Moreover, you can learn more from the unit testing project for the System.Text.Json namespace at this GitHub repo as well.

Thanks for reading. Happy coding.

codeburst

Bursts of code to power through your day. Web Development articles, tutorials, and news.

Changhui Xu

Written by

Senior Application Developer at the University of Iowa. Microsoft Certified Solutions Developer. AWS Certified Developer — Associate.

codeburst

Bursts of code to power through your day. Web Development articles, tutorials, and news.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade