Lenguaje

Uso de Utf8JsonWriter en System.Text.Json

En este artículo se muestra cómo usar el Utf8JsonWriter tipo para crear serializadores personalizados.

Utf8JsonWriter ofrece una forma de escribir texto JSON con codificación UTF-8 de alto rendimiento a partir de tipos de .NET comunes como String, Int32 y DateTime. El escritor es un tipo de bajo nivel que se puede usar para compilar serializadores personalizados. El JsonSerializer.Serialize método usa Utf8JsonWriter en segundo plano.

En el ejemplo siguiente se muestra cómo usar la Utf8JsonWriter clase :

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 un redactor

A partir de .NET 11, llame a Reset(Stream, JsonWriterOptions) o a Reset(IBufferWriter<Byte>, JsonWriterOptions) para reutilizar un escritor. Estas sobrecargas modifican el destino y las opciones sin crear ningún Utf8JsonWriter adicional.

Antes de restablecer el escritor, finaliza la carga JSON actual y llama a Flush. Reset borra el estado del escritor y no vacía la salida pendiente:

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

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

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

Escritura con texto UTF-8

Para lograr el mejor rendimiento posible al usar Utf8JsonWriter, escriba cargas JSON ya codificadas como texto UTF-8 en lugar de como cadenas UTF-16. Use JsonEncodedText para almacenar en caché y precodificar los nombres y valores conocidos de las propiedades de tipo cadena como valores estáticos, y páselos al escritor en lugar de utilizar literales de cadena UTF-16. Esto es más rápido que el almacenamiento en caché y el uso de matrices de bytes UTF-8.

Este enfoque también funciona si necesita realizar un escape personalizado. System.Text.Json no permite deshabilitar el escape al escribir una cadena. Sin embargo, podría proporcionar su propio JavaScriptEncoder personalizado como opción al writer, o crear su propio JsonEncodedText que use su JavascriptEncoder para efectuar el escape y, a continuación, escribir el JsonEncodedText en lugar de la cadena. Para obtener más información, consulte Personalización de la codificación de caracteres.

Escribir JSON sin procesar

En algunos escenarios, es posible que quiera escribir json "sin procesar" en una carga JSON que va a crear con Utf8JsonWriter. Puede usar Utf8JsonWriter.WriteRawValue para hacer eso. Estos son escenarios típicos:

  • Tiene una carga JSON existente que desea incluir en el nuevo JSON.

  • Quiere dar formato a los valores de forma diferente del formato predeterminado Utf8JsonWriter .

    Por ejemplo, puede que quiera personalizar el formato de número. De forma predeterminada, System.Text.Json omite el separador decimal de los números enteros, escribiendo 1 en lugar 1.0de , por ejemplo. La razón es que escribir menos bytes es bueno para el rendimiento. Pero supongamos que el consumidor de JSON trata los números con decimales como dobles y números sin decimales como enteros. Es posible que desee asegurarse de que todos los números de una matriz se reconozcan como dobles, escribiendo un separador decimal y cero para números enteros. En el siguiente ejemplo se muestra cómo hacerlo:

    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
    //    }
    //  ]
    //}
    

Personalización del escape de caracteres

La configuración StringEscapeHandling de JsonTextWriter ofrece opciones para escapar todos los caracteres no ASCII o los caracteres HTML. De forma predeterminada, Utf8JsonWriter convierte todos los caracteres que no son ASCII y HTML. Este proceso de escape se realiza por motivos de seguridad relacionados con la defensa en profundidad. Para especificar una política de escape diferente, cree un JavaScriptEncoder y establezca JsonWriterOptions.Encoder. Para obtener más información, consulte Personalización de la codificación de caracteres.

Escribir valores NULL

Para escribir valores NULL mediante Utf8JsonWriter, llame a:

  • WriteNull para escribir un par clave-valor con null como valor.
  • WriteNullValue para escribir null como elemento de una matriz JSON.

Para una propiedad de cadena, si la cadena es null y WriteStringValueWriteString son equivalentes a WriteNull y WriteNullValue.

Escribe valores TimeSpan, URI o char

Para escribir Timespan, Urio char valores, dé formato a ellos como cadenas (llamando a ToString(), por ejemplo) y llame a WriteStringValue.

Consulte también