Langue

Comment utiliser Utf8JsonWriter dans System.Text.Json

Cet article montre comment utiliser le Utf8JsonWriter type pour créer des sérialiseurs personnalisés.

Utf8JsonWriter fournit un moyen d’écrire du texte JSON encodé en UTF-8 à partir de types .NET courants, comme String, Int32, et DateTime. L’enregistreur est un type de bas niveau, permettant de générer des sérialiseurs personnalisés. La JsonSerializer.Serialize méthode utilise Utf8JsonWriter sous les couvertures.

L’exemple suivant montre comment utiliser la 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)

Réutiliser un rédacteur

À partir de .NET 11, appelez Reset(Stream, JsonWriterOptions) ou Reset(IBufferWriter<Byte>, JsonWriterOptions) pour réutiliser un writer. Ces surcharges modifient la destination et les options sans allouer un autre Utf8JsonWriter.

Avant de réinitialiser l’enregistreur, terminez la charge utile JSON actuelle et appelez Flush. Reset efface l’état de l’enregistreur et ne vide pas la sortie en attente :

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

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

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

Écrire avec du texte UTF-8

Pour obtenir les meilleures performances possibles lors de l’utilisation des Utf8JsonWritercharges utiles JSON, écrivez des charges utiles JSON déjà encodées en tant que texte UTF-8 plutôt que sous forme de chaînes UTF-16. Utilisez JsonEncodedText pour mettre en cache et préencoder les noms et les valeurs des propriétés de type chaîne connus sous forme de valeurs statiques, puis transmettez-les à l’objet writer, plutôt que d’utiliser des littéraux de chaîne UTF-16. Cela est plus rapide que la mise en cache et l’utilisation de tableaux d’octets UTF-8.

Cette approche fonctionne également si vous devez effectuer un échappement personnalisé. System.Text.Json ne vous permet pas de désactiver l’échappement lors de l’écriture d’une chaîne de caractères. Toutefois, vous pouvez transmettre votre propre JavaScriptEncoder personnalisé en tant qu’option à l’enregistreur, ou créer votre propre JsonEncodedText qui utilise votre JavascriptEncoder pour effectuer l’échappement, puis écrire le JsonEncodedText au lieu de la chaîne. Pour plus d’informations, consultez Personnaliser l’encodage de caractères.

Écrire un JSON brut

Dans certains scénarios, vous pouvez écrire un JSON « brut » dans une charge utile JSON que vous créez avec Utf8JsonWriter. Vous pouvez l’utiliser Utf8JsonWriter.WriteRawValue pour le faire. Voici des scénarios classiques :

  • Vous disposez d’une charge utile JSON existante que vous souhaitez placer dans un nouveau JSON.

  • Vous souhaitez mettre en forme les valeurs différemment de la mise en forme par défaut Utf8JsonWriter .

    Par exemple, vous pouvez personnaliser la mise en forme des nombres. Par défaut, System.Text.Json omettez le point décimal pour les nombres entiers, en écrivant 1 plutôt que 1.0, par exemple. La raison est que l’écriture de moins d’octets est bonne pour les performances. Toutefois, supposons que le consommateur de votre JSON traite les nombres avec des décimales comme des doubles et des nombres sans décimales comme entiers. Vous souhaiterez peut-être vous assurer que les nombres d’un tableau sont tous reconnus comme doubles, en écrivant un nombre décimal et zéro pour les nombres entiers. L’exemple suivant montre comment effectuer cette opération :

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

Personnaliser l’échappement de caractères

Le paramètre StringEscapeHandling de JsonTextWriter offre des options pour échapper tous les caractères non ASCII ou les caractères HTML. Par défaut, Utf8JsonWriter échappe tous les caractères non ASCII et HTML. Cet échappement est effectué pour des raisons de sécurité, dans le cadre d’une défense en profondeur. Pour spécifier une stratégie d’échappement différente, créez une JavaScriptEncoder stratégie et définissez JsonWriterOptions.Encoder. Pour plus d’informations, consultez Personnaliser l’encodage de caractères.

Écrire des valeurs nulles

Pour écrire des valeurs nulles à l’aide de Utf8JsonWriter, appelez :

  • WriteNull pour écrire une paire clé-valeur avec null comme valeur.
  • WriteNullValue pour écrire null en tant qu’élément d’un tableau JSON.

Pour une propriété de chaîne, si la chaîne est null et WriteStringWriteStringValue est équivalente à WriteNull et WriteNullValue.

Écrire des valeurs d’intervalle de temps, d’URI ou de char

Pour écrire Timespan, Uriou char des valeurs, les mettre en forme en tant que chaînes ( ToString()par exemple) et appeler WriteStringValue.

Voir aussi