Поделиться через


Как настроить кодировку символов с помощью System.Text.Json

По умолчанию сериализатор экранирует символы, отличные от ASCII. То есть он заменяет их на \uxxxx, где xxxx является кодом в кодировке Юникода символа. Например, если свойству Summary в следующем коде JSON присвоено кириллическое значение жарко, то объект WeatherForecast сериализуется, как показано в этом примере:

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

Сериализация кодировки языка

Чтобы сериализовать кодировки одного или нескольких языков без экранирования, укажите диапазон символов Юникода при создании экземпляра System.Text.Encodings.Web.JavaScriptEncoder, как показано в следующем примере:

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)

Этот код не поддерживает символы кириллицы или греческого языка. Если свойству Summary присвоено кириллическое значение жарко, то объект WeatherForecast сериализуется, как показано в этом примере:

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

По умолчанию кодировщик инициализируется с диапазоном BasicLatin .

Чтобы сериализовать все кодировки языка без экранирования, используйте UnicodeRanges.All.

Сериализация определенных символов

В качестве альтернативного способа вы можете указать отдельные символы, которые нужно разрешить, без экранирования. В следующем примере сериализуются только первые два символа слова жарко:

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)

Ниже приведен пример JSON, созданный с помощью приведенного выше кода.

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

Списки блокировок

В предыдущих разделах показано, как указать списки разрешенных точек кода или диапазонов, которые не нужно экранировать. Однако существуют глобальные списки блокировок, зависящие от кодировщика, которые могут переопределить определенные точки кода в списке разрешений. Точки кода в списке блокировок всегда экранируются, даже если они включены в список разрешений.

Глобальный список блокировок

Глобальный список блокировок включает такие элементы, как символы частного использования, символы управления, неопределенные кодовые точки и некоторые категории Юникода, такие как категория Space_Separator, за исключением U+0020 SPACE. Например, экранируется, U+3000 IDEOGRAPHIC SPACE даже если в качестве списка разрешений указан диапазон CJK в Юникоде (U+3000-U+303F).

Глобальный список блокировок — это сведения о реализации, которые изменились в каждом выпуске .NET. Не зависимостей от символа, являющегося членом (или не являющегося членом) глобального списка блокировок.

Списки блокировок для кодировщика

Примеры блокированных точек кода для кодировщика включают в себя кодировщик HTML, '\'кодировщик JSON и '%'кодировщик URL-адресов.'<''&' Например, кодировщик HTML всегда экранирует амперсанды ('&'), даже если амперсанд находится в BasicLatin диапазоне, и все кодировщики инициализированы по BasicLatin умолчанию.

Сериализация всех символов

Чтобы минимизировать экранирование, можно использовать JavaScriptEncoder.UnsafeRelaxedJsonEscaping, как показано в следующем примере:

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)

Внимание

По сравнению с кодировщиком по умолчанию, кодировщик UnsafeRelaxedJsonEscaping более предпочтителен в отношении передачи символов без экранирования:

  • Он не выполняет экранирование символов, учитывающих HTML, например <, >, & и '.
  • Он не предоставляет никаких дополнительных средств защиты от атак с помощью XSS или раскрытия информации, которые, например, могут возникать из-за того, что клиент и сервер не согласны с кодировкой.

Используйте ненадежный кодировщик, только если известно, что клиент будет интерпретировать полученные полезные данные как JSON в кодировке UTF-8. Например, его можно использовать, если сервер отправляет заголовок ответа Content-Type: application/json; charset=utf-8. Никогда не допускайте, чтобы необработанные выходные данные UnsafeRelaxedJsonEscaping выводились на HTML-страницу или в элемент <script>.

См. также