Как настроить кодировку символов с помощью 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>
.