JsonDocument Parsing
Introduction
Parsing and processing JSON is a common task when you need to process input from a web service or produce output as part of a web service. In the past when you wanted to work with JSON you could either write your own processor (tedious and why reinvent the wheel?) or you could include a third party package to help you process it. One of the most popular and powerful package for this was Newtonsoft.JSON
.
- Introduction
- Use Case
- Methods
- Parse() Method
- Method 1: Parse a String
- Method 2: Parse a Stream
- RootElement Property
- Conclusion
Newtonsoft.JSON
is still a great choice for processing JSON. With the .NET Core and .NET 5 you now have another choice which is built into .NET and does not require you to import a third party package in the System.Text.Json
namespace. According to the online documentation, System.Text.Json
is a standards-compliant and high performance JSON processor.
Use Case
A good use case for JsonDocument
is when you might want to inspect or utilize only a specific portion of JSON content and do not want to incur all of the overhead of instantiating object(s) to represent the data. If you have a large set of JSON content and only need a single property within that content then a JsonDocument
can help to avoid the overhead of de-serializing the content and using lots of memory that you will ultimately just throw away.
Methods
There are several methods we can use to process JSON content. We are going to look at the Parse methods.
Parse() Method
The Parse() method will parse UTF-8 encoded text that represents JSON into a JsonDocument. There are several different overloads of this method that can be used. You can parse the text from a Stream, a Byte sequence, memory or a String.
Method 1: Parse a String
It is common that a a String will contain JSON text and need to be parsed. The String could be loaded from a file or from a Url. For our example we will use the following JSON.
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"full_name": "Genevieve Mckenzie",
"first_name": "Booker",
"last_name": "Morrow",
"company": "BIOTICA",
"email": "booker.morrow@biotica.ca",
"last_login": "2019-01-27T05:41:26",
"date_joined": "2015-12-07T22:18:04",
"groups": [
1,
18,
35
],
"teams": [],
"member_of": [
200,
219,
238
],
"id": 0
}
]
}
Now that we have some JSON encoded text we can create a new JsonDocument
.
JsonDocument jsonDocument = JsonDocument.Parse(jsonString);
That is it. We now have a JsonDocument
that contains the JSON encoded text. Of course this doesn't do much for us. We need some way to see what is in the document so that we can do something useful. We can start inspecting the JsonDocument
by getting the root element of the document.
Method 2: Parse a Stream
If the JSON that you need to inspect is in a file or located at a URL you can parse the Stream to get the information.
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
jsonDocument = JsonDocument.Parse(fs);
}
RootElement Property
To get the root element we access the RootElement
property of the jsonDocument
. This will return a JsonElement
that we can use to inspect the document. The root element is the first token in the document and is a BeginObject token, the open curly brace "{".
JsonElement rootElement = jsonDocument.RootElement;
With the rootElement we can get a specific property we want. To get the count property we would use the GetProperty()
method.
JsonElement rootElement = jsonDocument.RootElement;
JsonElement element = rootElement.GetProperty("count");
If we want to then get the value of the count element we can use one of the Get*()
methods. If you try to use a Get*()
method that is not valid for the value type it will throw an exception. You can ensure that you are using the proper method by inspecting the ValueKind
property of the element to ensure it is the proper type.
The GetProperty()
method will only get a property that is at the same level as the current element. If you wanted to get the full_name
of the first object in the results array you would not be able to call GetProperty()
on the rootElement. This would result in an exception being thrown.
// You can only get properties that are at the same level as the JsonElement
try
{
element = rootElement.GetProperty("full_name");
Console.WriteLine("{0} {1}", element.ValueKind, element.GetRawText()); // Number
}
catch { Console.WriteLine("Exception as expected"); }
If you want to get a property from one of the objects in results you would need to first get the results property. Since this is an array, the ValueKind of the element will be returned as an Array. To get to an element of the array we can use the EnumerateArray()
method.
You can use a number of different methods to get the element you want from the array. You could create a foreach loop to inspect each object or you can use LINQ to get a specific object in the array. Since the individual properties of the objects are at one level deeper than the object in the array you still cannot access the properties of the objects directly. If you tried to access full_name
from the Array element you would get an exception.
// We cannot access an individual property of an object from an Array
try
{
element = elementArray.GetProperty("full_name");
Console.WriteLine("{0} {1}", element.ValueKind, element.GetRawText()); // Number
}
catch { Console.WriteLine("Exception as expected"); }
To access a property within an object in the array you must reference a specific object index in the array. Once you have a reference to a specific object in the array you can finally access full_name
.
// Grab the first element (a JSON Object) in the array using LINQ.
element = elementArray.EnumerateArray().First();
Console.WriteLine("{0}", element.ValueKind); // Object
// Reference an object in the array using Item[index]
element = elementArray[1];
Console.WriteLine("{0} {1}", element.ValueKind, element.GetRawText()); // Object
// Access a property of the object.
Console.WriteLine("{0} {1}", element.GetProperty("full_name").ValueKind, element.GetProperty("full_name").GetRawText()); // Number
Conclusion
The JsonDocument
class of System.Text.Json
namespace can be useful when you need to parse JSON text and inspect it without the need to allocate memory or create an object for the entire structure.
You must be logged in to see the comments. Log in now!