How to use Utf8JsonWriter in System.Text.Json
This article shows how to use the Utf8JsonWriter type for building custom serializers.
Utf8JsonWriter is a high-performance way to write UTF-8 encoded JSON text from common .NET types like String
, Int32
, and DateTime
. The writer is a low-level type that can be used to build custom serializers. The JsonSerializer.Serialize method uses Utf8JsonWriter
under the covers.
The following example shows how to use the Utf8JsonWriter class:
var options = new JsonWriterOptions
{
Indented = true
};
using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream, options);
writer.WriteStartObject();
writer.WriteString("date", DateTimeOffset.UtcNow);
writer.WriteNumber("temp", 42);
writer.WriteEndObject();
writer.Flush();
string json = Encoding.UTF8.GetString(stream.ToArray());
Console.WriteLine(json);
Dim options As JsonWriterOptions = New JsonWriterOptions With {
.Indented = True
}
Dim stream As MemoryStream = New MemoryStream
Dim writer As Utf8JsonWriter = New Utf8JsonWriter(stream, options)
writer.WriteStartObject()
writer.WriteString("date", DateTimeOffset.UtcNow)
writer.WriteNumber("temp", 42)
writer.WriteEndObject()
writer.Flush()
Dim json As String = Encoding.UTF8.GetString(stream.ToArray())
Console.WriteLine(json)
Write with UTF-8 text
To achieve the best possible performance while using the Utf8JsonWriter
, write JSON payloads already encoded as UTF-8 text rather than as UTF-16 strings. Use JsonEncodedText to cache and pre-encode known string property names and values as statics, and pass those to the writer, rather than using UTF-16 string literals. This is faster than caching and using UTF-8 byte arrays.
This approach also works if you need to do custom escaping. System.Text.Json
doesn't let you disable escaping while writing a string. However, you could pass in your own custom JavaScriptEncoder as an option to the writer, or create your own JsonEncodedText
that uses your JavascriptEncoder
to do the escaping, and then write the JsonEncodedText
instead of the string. For more information, see Customize character encoding.
Write raw JSON
In some scenarios, you might want to write "raw" JSON to a JSON payload that you're creating with Utf8JsonWriter
. You can use Utf8JsonWriter.WriteRawValue to do that. Here are typical scenarios:
You have an existing JSON payload that you want to enclose in new JSON.
You want to format values differently from the default
Utf8JsonWriter
formatting.For example, you might want to customize number formatting. By default, System.Text.Json omits the decimal point for whole numbers, writing
1
rather than1.0
, for example. The rationale is that writing fewer bytes is good for performance. But suppose the consumer of your JSON treats numbers with decimals as doubles, and numbers without decimals as integers. You might want to ensure that the numbers in an array are all recognized as doubles, by writing a decimal point and zero for whole numbers. The following example shows how to do that:using System.Text; using System.Text.Json; namespace WriteRawJson; public class Program { public static void Main() { JsonWriterOptions writerOptions = new() { Indented = true, }; using MemoryStream stream = new(); using Utf8JsonWriter writer = new(stream, writerOptions); writer.WriteStartObject(); writer.WriteStartArray("defaultJsonFormatting"); foreach (double number in new double[] { 50.4, 51 }) { writer.WriteStartObject(); writer.WritePropertyName("value"); writer.WriteNumberValue(number); writer.WriteEndObject(); } writer.WriteEndArray(); writer.WriteStartArray("customJsonFormatting"); foreach (double result in new double[] { 50.4, 51 }) { writer.WriteStartObject(); writer.WritePropertyName("value"); writer.WriteRawValue( FormatNumberValue(result), skipInputValidation: true); writer.WriteEndObject(); } writer.WriteEndArray(); writer.WriteEndObject(); writer.Flush(); string json = Encoding.UTF8.GetString(stream.ToArray()); Console.WriteLine(json); } static string FormatNumberValue(double numberValue) { return numberValue == Convert.ToInt32(numberValue) ? numberValue.ToString() + ".0" : numberValue.ToString(); } } // output: //{ // "defaultJsonFormatting": [ // { // "value": 50.4 // }, // { // "value": 51 // } // ], // "customJsonFormatting": [ // { // "value": 50.4 // }, // { // "value": 51.0 // } // ] //}
Customize character escaping
The StringEscapeHandling setting of JsonTextWriter
offers options to escape all non-ASCII characters or HTML characters. By default, Utf8JsonWriter
escapes all non-ASCII and HTML characters. This escaping is done for defense-in-depth security reasons. To specify a different escaping policy, create a JavaScriptEncoder and set JsonWriterOptions.Encoder. For more information, see Customize character encoding.
Write null values
To write null values by using Utf8JsonWriter
, call:
- WriteNull to write a key-value pair with null as the value.
- WriteNullValue to write null as an element of a JSON array.
For a string property, if the string is null, WriteString and WriteStringValue are equivalent to WriteNull
and WriteNullValue
.
Write Timespan, Uri, or char values
To write Timespan
, Uri
, or char
values, format them as strings (by calling ToString()
, for example) and call WriteStringValue.