Использование Utf8JsonWriter в System.Text.Json
В этой статье показано, как использовать Utf8JsonWriter тип для создания пользовательских сериализаторов.
Utf8JsonWriter — это высокопроизводительный способ записать текст JSON в кодировке UTF-8 из распространенных типов .NET, например String
, Int32
и DateTime
. Модуль записи — это низкоуровневый тип, с помощью которого можно создавать пользовательские сериализаторы. Метод JsonSerializer.Serialize использует Utf8JsonWriter
, как описано выше.
В следующем примере показано, как использовать класс Utf8JsonWriter.
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)
Запись с помощью текста UTF-8
Для достижения наилучшей производительности при использовании Utf8JsonWriter
записывайте полезные данные JSON, уже закодированные как текст UTF-8, а не как строки UTF-16. Используйте JsonEncodedText, чтобы кэшировать и предварительно закодировать известные имена и значения свойств строки как статические, а затем передать их в модуль записи вместо использования строковых литералов UTF-16. Это быстрее, чем кэширование и использование байтовых массивов UTF-8.
Этот подход также работает, если необходимо выполнить пользовательское экранирование. System.Text.Json
не позволяет отключить экранирование при записи строки. Однако можно передать собственный пользовательский JavaScriptEncoder в качестве параметра для модуля записи или создать собственный JsonEncodedText
, который использует JavascriptEncoder
для выполнения экранирования, а затем написать JsonEncodedText
вместо строки. Дополнительные сведения см. в статье Настройка кодировки символов.
Запись необработанного JSON
В некоторых сценариях может потребоваться записать "необработанный" JSON в полезные данные JSON, с помощью которого вы создаете Utf8JsonWriter
. Это можно использовать Utf8JsonWriter.WriteRawValue . Ниже приведены типичные сценарии.
У вас есть существующие полезные данные JSON, которые необходимо заключить в новый JSON.
Вы хотите отформатировать значения по-разному от форматирования по умолчанию
Utf8JsonWriter
.Например, может потребоваться настроить форматирование чисел. По умолчанию System.Text.Json десятичная точка для целых чисел не записывается,
1
например1.0
. Обоснование заключается в том, что запись меньше байтов хорошо подходит для производительности. Но предположим, что потребитель JSON обрабатывает числа с десятичными числами как двойные, а числа без десятичных разрядов — целыми числами. Возможно, необходимо убедиться, что числа в массиве распознаются как двойные, записав десятичную точку и ноль для целых чисел. Следующий пример показывает, как это сделать: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 // } // ] //}
Настройка экранирования символов
Параметр StringEscapeHandlingJsonTextWriter
предлагает варианты для экранирования всех символов, не являющихся символами ASCII, или символов HTML. По умолчанию Utf8JsonWriter
экранирует все символы, отличные от ASCII, и символы HTML. Такое экранирование выполняется в целях глубокой защиты. Чтобы указать другую политику экранирования, создайте JavaScriptEncoder и задайте JsonWriterOptions.Encoder. Дополнительные сведения см. в статье Настройка кодировки символов.
Запись значений NULL
Чтобы записать значения NULL с помощью Utf8JsonWriter
, вызовите:
- WriteNull для записи пары "ключ-значение" со значением NULL.
- WriteNullValue для записи значения NULL в качестве элемента массива JSON.
Для строкового свойства, если строка имеет значение NULL, WriteString и WriteStringValue эквивалентны WriteNull
и WriteNullValue
.
Запись значений TimeSpan, URI или char
Для записи или Uri
char
значений отформатируйте Timespan
их как строки (например, вызовToString()
) и вызовWriteStringValue.