Partage via


Comment utiliser Utf8JsonWriter dans System.Text.Json

Cet article montre comment utiliser le type Utf8JsonWriter 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 méthode JsonSerializer.Serialize utilise Utf8JsonWriter en coulisses.

L’exemple suivant illustre la 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)

Écrire avec du texte UTF-8

Pour obtenir les meilleures performances possibles lors de l’utilisation de Utf8JsonWriter, é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 de propriétés de chaîne connus et les valeurs en tant que statiques, et passez-les à l’enregistreur, 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. 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 du JSON brut

Dans certains scénarios, vous pouvez écrire du JSON « brut » dans une charge utile JSON que vous créez avec Utf8JsonWriter. Vous pouvez utiliser pour cela la commande Utf8JsonWriter.WriteRawValue. Voici les scénarios classiques :

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

  • Vous souhaitez mettre en forme les valeurs différemment du format Utf8JsonWriter par défaut.

    Par exemple, vous pouvez personnaliser la mise en forme des nombres. Par défaut, System.Text.Json omet la virgule décimale pour les nombres entiers, en écrivant 1 plutôt que 1.0, par exemple. Le raisonnement est que l’écriture de moins d’octets est bonne pour les performances. Mais supposons que le consommateur de votre JSON traite les nombres avec des décimales comme des doubles et les nombres sans décimales comme des entiers. Vous souhaiterez peut-être vous assurer que les nombres d’un tableau sont tous reconnus en tant que doubles, en écrivant une virgule décimale 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 d’échappement de tous les caractères non ASCII ou HTML. Par défaut, Utf8JsonWriter échappe tous les caractères non ASCII et HTML. Cet échappement est effectué pour des raisons de sécurité de défense en profondeur. Pour spécifier une autre stratégie d’échappement, créez un JavaScriptEncoder et définissez JsonWriterOptions.Encoder. Pour plus d’informations, consultez Personnaliser l’encodage de caractères.

Écrire des valeurs null

Pour écrire des valeurs null à 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é string, si la chaîne a la valeur null, WriteString et WriteStringValue sont équivalents à WriteNull et WriteNullValue.

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

Pour écrire des valeurs Timespan, Uri ou char, formatez-les en tant que chaînes (en appelant ToString(), par exemple) et appelez WriteStringValue.

Voir aussi