Jak używać narzędzia Utf8JsonWriter w programie System.Text.Json

W tym artykule pokazano, jak używać Utf8JsonWriter typu do tworzenia niestandardowych serializatorów.

Utf8JsonWriter to wysokowydajny sposób pisania zakodowanego w formacie UTF-8 tekstu JSON z typowych typów platformy .NET, takich jak String, Int32i DateTime. Moduł zapisywania jest typem niskiego poziomu, który może służyć do tworzenia niestandardowych serializatorów. Metoda JsonSerializer.Serialize używa Utf8JsonWriter w ramach okładek.

W poniższym przykładzie pokazano, jak używać Utf8JsonWriter klasy:

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)

Pisanie przy użyciu tekstu UTF-8

Aby uzyskać najlepszą możliwą wydajność podczas używania Utf8JsonWriter, zapisuj ładunki JSON już zakodowane jako tekst UTF-8, a nie jako ciągi UTF-16. Służy JsonEncodedText do buforowania i wstępnego kodowania znanych nazw i wartości ciągów jako statycznych, a następnie przekazywania ich do składnika zapisywania, zamiast używać literałów ciągów UTF-16. Jest to szybsze niż buforowanie i używanie tablic bajtów UTF-8.

Takie podejście działa również w przypadku konieczności wykonania niestandardowego ucieczki. System.Text.Json nie pozwala wyłączyć ucieczki podczas pisania ciągu. Można jednak przekazać własny niestandardowy JavaScriptEncoder element jako opcję modułu zapisywania lub utworzyć własny JsonEncodedText , który używa JavascriptEncoder elementu do ucieczki, a następnie napisać JsonEncodedText zamiast ciągu. Aby uzyskać więcej informacji, zobacz Dostosowywanie kodowania znaków.

Zapisywanie nieprzetworzonego kodu JSON

W niektórych scenariuszach możesz chcieć zapisać kod JSON "raw" do ładunku JSON tworzonego za pomocą polecenia Utf8JsonWriter. Możesz to zrobić za pomocą Utf8JsonWriter.WriteRawValue polecenia . Oto typowe scenariusze:

  • Masz istniejący ładunek JSON, który chcesz ująć w nowy kod JSON.

  • Chcesz formatować wartości inaczej niż domyślne Utf8JsonWriter formatowanie.

    Na przykład możesz dostosować formatowanie liczb. Domyślnie System.Text.Json pomija punkt dziesiętny dla liczb całkowitych, zapisując 1 zamiast 1.0, na przykład. Uzasadnieniem jest to, że zapisywanie mniejszej liczby bajtów jest dobre dla wydajności. Załóżmy jednak, że użytkownik kodu JSON traktuje liczby z liczbami dziesiętnymi jako liczbami podwójnymi i liczbami bez liczb dziesiętnych jako liczb całkowitych. Warto upewnić się, że liczby w tablicy są rozpoznawane jako podwójne, zapisując punkt dziesiętny i zero dla liczb całkowitych. W poniższym przykładzie pokazano, jak to zrobić:

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

Dostosowywanie ucieczki znaku

Ustawienie JsonTextWriter StringEscapeHandling ofert oferuje opcje ucieczki wszystkich znaków innych niż ASCII lub znaków HTML. Domyślnie wszystkie znaki inne niż ASCII i HTML są domyślnie Utf8JsonWriter ucieczki. To ucieczka jest wykonywana ze względów bezpieczeństwa w głębi systemu obrony. Aby określić inne zasady ucieczki, utwórz element JavaScriptEncoder i ustaw .JsonWriterOptions.Encoder Aby uzyskać więcej informacji, zobacz Dostosowywanie kodowania znaków.

Zapisywanie wartości null

Aby zapisać wartości null przy użyciu metody Utf8JsonWriter, wywołaj metodę :

  • WriteNull aby zapisać parę klucz-wartość z wartością null jako wartość.
  • WriteNullValue w celu zapisania wartości null jako elementu tablicy JSON.

W przypadku właściwości ciągu, jeśli ciąg ma wartość null, WriteString i są równoważne wartościom WriteStringValueWriteNull i WriteNullValue.

Zapisywanie wartości przedziału czasu, identyfikatora URI lub znaku

Aby zapisać Timespanwartości , Urilub char , sformatuj je jako ciągi (wywołując na przykład , i wywołaj ToString()metodę WriteStringValue.

Zobacz też