Como usar Utf8JsonWriter no System.Text.Json
Este artigo mostra como usar o tipo Utf8JsonWriter para criar serializadores personalizados.
Utf8JsonWriter é uma forma de alto desempenho para escrita de texto JSON codificado em UTF-8 com base em tipos .NET comuns como String
, Int32
e DateTime
. O gravador é um tipo de baixo nível que pode ser usado para criar serializadores personalizados. O método JsonSerializer.Serialize é usado sob as coberturas Utf8JsonWriter
.
O exemplo a seguir mostra como usar a classe 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)
Gravar com texto UTF-8
Para obter o melhor desempenho possível ao usar Utf8JsonWriter
, o conteúdo JSON de gravação já codificado como texto UTF-8 em vez de como cadeias de caracteres UTF-16. Use JsonEncodedText para armazenar em cache e pré-codificar nomes e valores de propriedade de cadeia de caracteres conhecidos como estáticos e passá-los para o gravador, em vez de usar literais de cadeia de caracteres UTF-16. Isso é mais rápido do que armazenar em cache e usar matrizes de bytes UTF-8.
Essa abordagem também funcionará se você precisar fazer escape personalizado. System.Text.Json
não permite desabilitar a fuga ao escrever uma cadeia de caracteres. No entanto, você pode passar seu próprio JavaScriptEncoder personalizado como uma opção para o gravador ou criar o seu próprio JsonEncodedText
que usa o JavascriptEncoder
para fazer o escape e, em seguida, gravar JsonEncodedText
em vez da cadeia de caracteres. Para obter mais informações, consulte Personalizar a codificação de caracteres.
Gravar JSON bruto
Em alguns cenários, convém gravar JSON "bruto" em um conteúdo JSON que você está criando com Utf8JsonWriter
. Você pode usar Utf8JsonWriter.WriteRawValue para fazer isso. Aqui estão cenários típicos:
Você tem um conteúdo JSON existente que deseja incluir no novo JSON.
Você deseja formatar valores de forma diferente da formatação padrão
Utf8JsonWriter
.Por exemplo, talvez você queira personalizar a formatação numérica. Por padrão, System.Text.Json omite o ponto decimal para números inteiros, escrevendo
1
em vez de1.0
, por exemplo. A lógica é que escrever menos bytes é bom para o desempenho. Mas suponha que o consumidor de seu JSON trate números com decimais como duplos e números sem decimais como inteiros. Talvez você queira garantir que os números em uma matriz sejam todos reconhecidos como duplos, escrevendo um ponto decimal e zero para números inteiros. O seguinte exemplo mostra como fazer isso: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 // } // ] //}
Personalizar codificação de caracteres
A configuração StringEscapeHandling de JsonTextWriter
oferece opções para escapar de todos os caracteres não ASCII ou caracteres HTML. Por padrão, Utf8JsonWriter
escapa todos os caracteres não ASCII e HTML. Esse escape é feita por razões de segurança detalhadas. Para especificar uma política de escape diferente, crie JavaScriptEncoder e defina JsonWriterOptions.Encoder. Para obter mais informações, consulte Personalizar a codificação de caracteres.
Grave valores nulos
Para gravar valores nulos usando Utf8JsonWriter
, chame:
- WriteNull para gravar um par de chaves-valor com nulo como o valor.
- WriteNullValue para escrever null como um elemento de uma matriz JSON.
Para uma propriedade de cadeia de caracteres, se a cadeia de caracteres for nula, WriteString e WriteStringValue for equivalente a WriteNull
e WriteNullValue
.
Gravar valores de Timespan, Uri ou char
Para gravar valores Timespan
, Uri
ou char
, formatá-los como cadeias de caracteres (chamando ToString()
, por exemplo) e chamar WriteStringValue.