默认情况下,序列化程序会转义所有非 ASCII 字符。 即,会将它们替换为
\uxxxx
,其中
xxxx
为字符的 Unicode 代码。 例如,如果以下 JSON 中的
Summary
属性设置为西里尔文
жарко
,则
WeatherForecast
对象会进行序列化,如以下示例中所示:
"Date": "2019-08-01T00:00:00-07:00",
"TemperatureCelsius": 25,
"Summary": "\u0436\u0430\u0440\u043A\u043E"
序列化语言字符集
若要序列化一种或多种语言的字符集而不进行转义,请在创建
System.Text.Encodings.Web.JavaScriptEncoder
的实例时指定
Unicode 范围
,如以下示例中所示:
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"
前面的部分显示了如何指定不希望转义的码位或范围的允许列表。 但是,存在一些全局和编码器特定的阻止列表,它们可覆盖允许列表中的某些码位。 阻止列表中的码位总是进行转义,即使它们包含在允许列表中也是如此。
全局阻止列表
全局阻止列表包括专用字符、控制字符、未定义的码位和某些 Unicode 类别(如
Space_Separator 类别
)等内容,但不包含
U+0020 SPACE
。 例如,即使指定 Unicode 范围
CJK 符号和标点 (U+3000-U+303F)
作为允许列表,也会对
U+3000 IDEOGRAPHIC SPACE
进行转义。
全局阻止列表是一个实现细节,在 .NET Core 的每个版本和 .NET 5 中都有所更改。 不要依赖于全局阻止列表中包含(或未包含)的字符。
编码器特定的阻止列表
对于
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 或信息泄露攻击(如客户端和服务器在字符集方面不一致所可能导致的攻击)的额外深度防御保护。
仅当知道客户端将生成的有效负载解释为 UTF-8 编码的 JSON 时,才使用不安全编码器。 例如,如果服务器在发送响应标头
Content-Type: application/json; charset=utf-8
,则可以使用它。 永远不允许将原始
UnsafeRelaxedJsonEscaping
输出发出到 HTML 页面或
<script>
元素。
System.Text.Json 概述
如何对 JSON 进行序列化和反序列化