Como usar Utf8JsonWriter em System.Text.Json

Este artigo mostra como usar o Utf8JsonWriter tipo para criar 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. O gravador é um tipo de baixo nível que pode ser usado para criar serializadores personalizados. O JsonSerializer.Serialize método é utilizado Utf8JsonWriter debaixo das cobertas.

O exemplo a seguir 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)

Escrever com texto UTF-8

Para obter o melhor desempenho possível ao usar o Utf8JsonWriter, escreva cargas úteis JSON já codificadas como texto UTF-8 em vez de 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 funciona se você precisar fazer fugas personalizadas. System.Text.Json não permite que você desative a fuga enquanto escreve uma cadeia de caracteres. No entanto, você pode passar seu próprio costume JavaScriptEncoder como uma opção para o escritor, ou criar o seu próprio JsonEncodedText que usa o seu JavascriptEncoder para fazer a fuga e, em seguida, escrever o JsonEncodedText em vez da string. Para obter mais informações, consulte Personalizar codificação de caracteres.

Escrever JSON bruto

Em alguns cenários, talvez você queira escrever JSON "bruto" em uma carga JSON que está criando com Utf8JsonWritero . Você pode usar Utf8JsonWriter.WriteRawValue para fazer isso. Aqui estão os cenários típicos:

  • Você tem uma carga 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 de números. Por padrão, System.Text.Json omite o ponto decimal para números inteiros, escrevendo 1 em vez de 1.0, por exemplo. A lógica é que escrever menos bytes é bom para o desempenho. Mas suponha que o consumidor do 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 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 a fuga de personagens

A configuração StringEscapeHandling de oferece opções para escapar de JsonTextWriter todos os caracteres não-ASCII ou caracteres HTML. Por padrão, Utf8JsonWriter escapa de todos os caracteres não-ASCII e HTML. Essa fuga é feita por razões de segurança de defesa em profundidade. Para especificar uma política de escape diferente, crie um JavaScriptEncoder e defina JsonWriterOptions.Encoder. Para obter mais informações, consulte Personalizar codificação de caracteres.

Gravar valores nulos

Para gravar valores nulos usando Utf8JsonWriter, chame:

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

Para uma propriedade string, WriteString se a string for null e WriteStringValue for equivalente a WriteNull e WriteNullValue.

Escrever valores de Timepan, Uri ou char

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

Consulte também