Idioma

Como usar o Utf8JsonWriter em System.Text.Json

Este artigo mostra como usar o Utf8JsonWriter tipo para construir serializadores personalizados.

Utf8JsonWriter é uma maneira de alto desempenho para escrever texto JSON codificado em UTF-8 a partir de tipos .NET comuns como String, Int32e DateTime. "Escritor é um tipo de baixo nível que pode ser usado para criar serializadores personalizados." O JsonSerializer.Serialize método utiliza Utf8JsonWriter internamente.

O exemplo seguinte mostra como usar a Utf8JsonWriter classe:

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)

Reutilizar um escritor

A partir do .NET 11, chame Reset(Stream, JsonWriterOptions) ou Reset(IBufferWriter<Byte>, JsonWriterOptions) para reutilizar um gravador. Estas sobrecargas alteram o destino e as opções sem alocar outra Utf8JsonWriter.

Antes de reiniciares o escritor, termina o payload JSON atual e chama Flush. Reset limpa o estado do escritor e não despeja a saída pendente:

writer.WriteEndObject();
writer.Flush();

writer.Reset(nextStream, new JsonWriterOptions { Indented = true });
writer.WriteEndObject()
writer.Flush()

writer.Reset(nextStream, New JsonWriterOptions With {.Indented = True})

Escrever com texto UTF-8

Para alcançar o melhor desempenho possível usando o Utf8JsonWriter, escreva cargas úteis JSON já codificadas como texto UTF-8 em vez de como strings UTF-16. Utilize JsonEncodedText para armazenar em cache e pré-codificar nomes e valores conhecidos de propriedades de cadeia de caracteres como elementos estáticos e passá-los ao gravador, em vez de utilizar literais de cadeia de caracteres UTF-16. Isto é mais rápido do que o cache e o uso de arrays de UTF-8 bytes.

Esta abordagem também funciona se precisares de fazer escape personalizado. System.Text.Json Não te permite desativar o escape enquanto escreves uma sequência. No entanto, podes passar o teu próprio JavaScriptEncoder personalizado como opção ao gravador, ou criar o teu próprio JsonEncodedText que use o teu JavascriptEncoder para efetuar o escape, e depois escrever o JsonEncodedText em vez da cadeia de caracteres. Para mais informações, consulte Personalizar codificação de caracteres.

Escrever JSON bruto

Em alguns cenários, pode querer escrever JSON "bruto" num payload JSON que está a criar com Utf8JsonWriter. Pode usar Utf8JsonWriter.WriteRawValue para fazer isso. Aqui estão cenários típicos:

  • Tem um payload JSON existente que pretende envolver num novo JSON.

  • Queres formatar valores de forma diferente da formatação padrão Utf8JsonWriter .

    Por exemplo, pode querer personalizar a formatação dos números. Por defeito, System.Text.Json omite o ponto decimal para números inteiros, escrevendo 1 em vez de 1.0, por exemplo. A razão é que escrever menos bytes é bom para o desempenho. Mas suponha que o consumidor do seu JSON trata números com decimais como duplos, e números sem decimais como inteiros. Pode querer garantir que os números num array são todos reconhecidos como duplos, escrevendo um ponto decimal e um zero para os números inteiros. O exemplo a seguir 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 escape de personagem

A definição StringEscapeHandling de JsonTextWriter oferece opções para escapar de todos os caracteres não-ASCII ou caracteres HTML. Por defeito, Utf8JsonWriter escapa a todos os caracteres que não sejam ASCII e HTML. Este escape é efetuado por motivos de segurança de defesa em profundidade. Para especificar uma política de escape diferente, crie um JavaScriptEncoder e defina JsonWriterOptions.Encoder. Para mais informações, consulte Personalizar codificação de caracteres.

Escrever valores nulos

Para escrever valores nulos por meio de Utf8JsonWriter, chame:

  • WriteNull para escrever um par chave-valor com null como valor.
  • WriteNullValue para escrever null como elemento de um array JSON.

Para uma propriedade de cadeia, se a cadeia for nula, WriteString e WriteStringValue são equivalentes a WriteNull e WriteNullValue.

Escreva valores de Timespan, Uri ou char

Para escrever Timespan, , ou char valores, formate-os como cadeias (chamando ToString(), por exemplo) e chame WriteStringValueUri.

Consulte também