Jak dostosować kodowanie znaków za pomocą polecenia System.Text.Json

Domyślnie serializator unika wszystkich znaków innych niż ASCII. Oznacza to, że zastępuje je \uxxxx gdzie xxxx to kod Unicode znaku. Jeśli na przykład Summary właściwość w następującym formacie JSON jest ustawiona na Cyrylica жарко, WeatherForecast obiekt jest serializowany, jak pokazano w tym przykładzie:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "\u0436\u0430\u0440\u043A\u043E"
}

Serializowanie zestawów znaków języka

Aby serializować zestawy znaków w co najmniej jednym językach bez ucieczki, określ zakresy Unicode podczas tworzenia wystąpienia System.Text.Encodings.Web.JavaScriptEncoder, jak pokazano w poniższym przykładzie:

using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
Imports System.Text.Encodings.Web
Imports System.Text.Json
Imports System.Text.Unicode
var options1 = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.Create(UnicodeRanges.BasicLatin, UnicodeRanges.Cyrillic),
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options1);
options = New JsonSerializerOptions With {
    .Encoder = JavaScriptEncoder.Create(UnicodeRanges.BasicLatin, UnicodeRanges.Cyrillic),
    .WriteIndented = True
}
jsonString = JsonSerializer.Serialize(weatherForecast1, options)

Ten kod nie powoduje ucieczki od znaków cyrylica ani greckich. Summary Jeśli właściwość jest ustawiona na Cyrylicaжарко, WeatherForecast obiekt jest serializowany, jak pokazano w tym przykładzie:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "жарко"
}

Domyślnie koder jest inicjowany z zakresem BasicLatin .

Aby serializować wszystkie zestawy języków bez ucieczki, użyj polecenia UnicodeRanges.All.

Serializowanie określonych znaków

Alternatywą jest określenie poszczególnych znaków, które mają być dozwolone bez ucieczki. Poniższy przykład serializuje tylko dwa pierwsze znaki жарко:

using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
Imports System.Text.Encodings.Web
Imports System.Text.Json
Imports System.Text.Unicode
var encoderSettings = new TextEncoderSettings();
encoderSettings.AllowCharacters('\u0436', '\u0430');
encoderSettings.AllowRange(UnicodeRanges.BasicLatin);
var options2 = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.Create(encoderSettings),
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options2);
Dim encoderSettings As TextEncoderSettings = New TextEncoderSettings
encoderSettings.AllowCharacters(ChrW(&H436), ChrW(&H430))
encoderSettings.AllowRange(UnicodeRanges.BasicLatin)
options = New JsonSerializerOptions With {
    .Encoder = JavaScriptEncoder.Create(encoderSettings),
    .WriteIndented = True
}
jsonString = JsonSerializer.Serialize(weatherForecast1, options)

Oto przykład kodu JSON wygenerowanego przez powyższy kod:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "жа\u0440\u043A\u043E"
}

Listy blokowe

W poprzednich sekcjach pokazano, jak określić listy dozwolonych punktów kodu lub zakresów, których nie chcesz unikać. Istnieją jednak globalne i specyficzne dla kodera listy bloków, które mogą zastąpić niektóre punkty kodu na liście dozwolonych. Punkty kodu na liście zablokowanych są zawsze usuwane, nawet jeśli znajdują się na liście dozwolonych.

Globalna lista bloków

Globalna lista bloków zawiera takie elementy jak znaki użytku prywatnego, znaki sterujące, niezdefiniowane punkty kodu i niektóre kategorie Unicode, takie jak kategoria Space_Separator, z wyłączeniem U+0020 SPACE. Na przykład jest on unikany, U+3000 IDEOGRAPHIC SPACE nawet jeśli jako listę dozwolonych określisz symbole CJK zakresu Unicode i znaki interpunkcyjne (U+3000-U+303F).

Globalna lista bloków to szczegóły implementacji, które uległy zmianie w każdej wersji platformy .NET. Nie należy przyjmować zależności od znaku będącego członkiem (lub nie jest członkiem) globalnej listy bloków.

Listy blokowe specyficzne dla kodera

Przykłady zablokowanych punktów kodu specyficznych dla kodera kodera obejmują '<' koder '&' HTML, '\' koder JSON i '%' koder URL. Na przykład koder HTML zawsze unika ampersands ('&'), mimo że ampersand znajduje się w BasicLatin zakresie, a wszystkie kodery są inicjowane BasicLatin domyślnie.

Serializowanie wszystkich znaków

Aby zminimalizować ucieczkę, możesz użyć metody JavaScriptEncoder.UnsafeRelaxedJsonEscaping, jak pokazano w poniższym przykładzie:

using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
Imports System.Text.Encodings.Web
Imports System.Text.Json
Imports System.Text.Unicode
var options3 = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options3);
options = New JsonSerializerOptions With {
    .Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    .WriteIndented = True
}
jsonString = JsonSerializer.Serialize(weatherForecast1, options)

Uwaga

W porównaniu z koderem domyślnym koder UnsafeRelaxedJsonEscaping jest bardziej permisywny, dzięki czemu znaki mogą przechodzić przez niewyobrażalne:

  • Nie powoduje to ucieczki znaków z uwzględnieniem kodu HTML, takich jak <, , >&i '.
  • Nie oferuje żadnych dodatkowych ochrony przed atakami XSS lub atakami ujawniania informacji, takimi jak te, które mogą wynikać z braku zgody klienta i serwera na zestaw znaków.

Użyj niebezpiecznego kodera tylko wtedy, gdy wiadomo, że klient będzie interpretował wynikowy ładunek jako kodowany kod JSON UTF-8. Na przykład można go użyć, jeśli serwer wysyła nagłówek Content-Type: application/json; charset=utf-8odpowiedzi . Nigdy nie zezwalaj na emitowanie nieprzetworzonych UnsafeRelaxedJsonEscaping danych wyjściowych do strony HTML lub elementu <script> .

Zobacz też