默认情况下,序列化程序会转义所有非 ASCII 字符。 即,会将它们替换为 \uxxxx
,其中 xxxx
为字符的 Unicode 代码。
例如,如果以下 JSON 中的 sign
属性为中文还有符号等 "中文 Holle Word abc 1+1<1>1&1'1$",则SingModel对象会进行序列化,如以下示例中所示:
//转Json之前
{
ver = "1.0",
identifier = "admin",
appid = 10000,
sign = "中文 Holle Word abc 1+1<1>1&1'1$"
}
//System.Text.Json转Json之后
{
ver = "1.0",
identifier = "admin",
appid = 10000,
sign = "\u4E2D\u6587 Holle Word abc 1\u002B1\u003C1\u003E1\u00261\u00271$"
}
解决办法:
一、序列化语言字符集
若要序列化一种或多种语言的字符集而不进行转义,请在创建 System.Text.Encodings.Web.JavaScriptEncoder 的实例时指定 Unicode 范围,如以下示例中所示:
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
options = new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.Create(UnicodeRanges.BasicLatin, UnicodeRanges.Cyrillic)
};
jsonString = JsonSerializer.Serialize(singModel, options);
此代码不转义西里尔文或希腊语字符。 如果 Summary
属性设置为西里尔文 жарко
,则 WeatherForecast
对象会进行序列化,如以下示例中所示:
若要序列化所有语言集而不进行转义,请使用 UnicodeRanges.All。
想了解其他的语言集,请移步:UnicodeRanges类
二、序列化特定字符
一种替代方法是指定要允许的单个字符,而不进行转义。 下面的示例仅序列化 жарко
的前两个字符:
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
var encoderSettings = new TextEncoderSettings();
encoderSettings.AllowCharacters('\u0436', '\u0430');
encoderSettings.AllowRange(UnicodeRanges.BasicLatin);
options = new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.Create(encoderSettings),
WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);
三、序列化所有字符(建议使用这种方式)
若要最大程度地减少转义,可以使用 JavaScriptEncoder.UnsafeRelaxedJsonEscaping,如以下示例中所示:
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
options = new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options);
注意
与默认编码器相比,UnsafeRelaxedJsonEscaping
编码器在允许字符通过而不进行转义方面更加宽松:
- 它不转义 HTML 敏感字符,如
<
、>
、&
和'
。 - 它不提供任何针对 XSS 或信息泄露攻击(如客户端和服务器在字符集方面不一致所可能导致的攻击)的额外深度防御保护。
仅当知道客户端将生成的有效负载解释为 UTF-8 编码的 JSON 时,才使用不安全编码器。 例如,如果服务器在发送响应标头 Content-Type: application/json; charset=utf-8
,则可以使用它。 永远不允许将原始 UnsafeRelaxedJsonEscaping
输出发出到 HTML 页面或 <script>
元素。
参考文档
1、如何使用 System.Text.Json 自定义字符编码 | Microsoft Docs
2、UnicodeRanges 类 (System.Text.Unicode) | Microsoft Docs
3、如何使用 System.Text.Json 自定义字符编码 | Microsoft Docs
4、JavaScriptEncoder.UnsafeRelaxedJsonEscaping 属性 | Microsoft Docs