dotnet核心System.Text.Json Unscape Unicode字符串

Joe*_*oey 1 .net c# json .net-core system.text.json

使用JsonSerializer.Serialize(obj);将产生一个转义的字符串,但我想要未转义的版本。例如:

using System;
using System.Text.Json;

public class Program
{
    public static void Main()
    {
            var a = new A{Name = "??"};
            var s = JsonSerializer.Serialize(a);
            Console.WriteLine(s);
        }
}

class A {
    public string Name {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

会产生一个字符串,{"Name":"\u4F60\u597D"}但我想要{"Name":"??"}

我在https://dotnetfiddle.net/w73vnO上创建了一个代码段,请帮助我。

ahs*_*han 24

要改变的逃逸行为JsonSerializer,你可以在自定义传递JavascriptEncoderJsonSerializer通过设置Encoder的财产JsonSerializerOptions

https://docs.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.encoder?view=netcore-3.0#System_Text_Json_JsonSerializerOptions_Encoder

默认行为的设计考虑了安全性和JsonSerializer纵深防御的过度逃避。

如果您正在寻找的只是转义特定非拉丁语言的某些“字母数字”字符,我建议您改为JavascriptEncoder使用Create工厂方法而不是使用UnsafeRelaxedJsonEscaping编码器创建一个。

JsonSerializerOptions options = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.Create(UnicodeRanges.BasicLatin, UnicodeRanges.CjkUnifiedIdeographs)
};

var a = new A { Name = "??" };
var s = JsonSerializer.Serialize(a, options);
Console.WriteLine(s);
Run Code Online (Sandbox Code Playgroud)

这样做可以保护某些安全措施,例如,HTML 敏感字符将继续被转义。

我会警告不要 System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping轻率地使用,因为它的转义最少(这就是为什么它的名称中有“不安全”)。如果您正在创建的 JSON 写入磁盘上的 UTF-8 编码文件,或者它的 Web 请求部分将字符集显式设置为 utf-8(并且不会按原样嵌入 HTML 组件中),那么使用它可能是可以的。

请参阅 API 文档中的备注部分:https : //docs.microsoft.com/en-us/dotnet/api/system.text.encodings.web.javascriptencoder.unsaferelaxedjsonescaping? view = netcore-3.0#remarks

您还可以考虑指定UnicodeRanges.All是否希望/需要所有语言都保持未转义。这仍然会转义某些容易出现安全漏洞的 ASCII 字符。

JsonSerializerOptions options = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
};
Run Code Online (Sandbox Code Playgroud)

有关详细信息和代码示例,请参阅https : //docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to?view=netcore-3.0#customize-character-encoding

请参阅注意事项

  • @joey我知道这是后来的,但它应该成为公认的答案 (3认同)

Cyr*_*rus 15

使用:

JsonSerializerOptions options = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
};
Run Code Online (Sandbox Code Playgroud)

  • 就是这样,谢谢 (2认同)

Ste*_*rce 11

您可以使用:System.Text.RegularExpressions.Regex.Unescape(string)对 unicode 字符进行转义。\n https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex.unescape

\n

更新原始问题的示例:

\n
using System;\nusing System.Text.Json;\n\npublic class Program\n{\n    public static void Main()\n    {\n            var a = new A{Name = "\xe4\xbd\xa0\xe5\xa5\xbd"};\n            var s = JsonSerializer.Serialize(a);\n        \n            var unescaped = System.Text.RegularExpressions.Regex.Unescape(s);\n\n            Console.WriteLine(s);\n            Console.WriteLine(unescaped);\n        }\n}\n\nclass A {\n    public string Name {get; set;}\n}\n
Run Code Online (Sandbox Code Playgroud)\n

输出:

\n
{"Name":"\\u4F60\\u597D"}\n{"Name":"\xe4\xbd\xa0\xe5\xa5\xbd"}\n
Run Code Online (Sandbox Code Playgroud)\n


rcs*_*rcs 5

您需要设置JsonSerializer选项,以不对那些字符串进行编码。

JsonSerializerOptions jso = new JsonSerializerOptions();
jso.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
Run Code Online (Sandbox Code Playgroud)

然后,在调用Serialize方法时传递此选项。

var s = JsonSerializer.Serialize(a, jso);        
Run Code Online (Sandbox Code Playgroud)

完整代码:

JsonSerializerOptions jso = new JsonSerializerOptions();
jso.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping;

var a = new A { Name = "??" };
var s = JsonSerializer.Serialize(a, jso);        
Console.WriteLine(s);
Run Code Online (Sandbox Code Playgroud)

结果:

在此处输入图片说明

如果需要在控制台中打印结果,则可能需要安装其他语言。请参考这里

  • 当我发现这个时,我简直不敢相信自己的眼睛:https://learn.microsoft.com/en-us/dotnet/api/system.text.encodings.web.javascriptencoder.unsaferelaxedjsonescaping?view=netcore-3.0 这非常令人惊讶默认编码器的行为。 (6认同)
  • 使用“不安全”编码不是答案,ahsonkhan 的答案是正确的 (5认同)
  • 这些文档从未提及_为什么_他们避免序列化它们。当双引号 `"` 和控制字符等字符具有特定的转义序列时,为什么决定对所有内容进行编码?! (4认同)
  • 了解在您的场景中使用此功能的潜在问题非常重要,如果可行,我会推荐更安全的替代方案。请参阅 https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to?view=netcore-3.0#serialize-all-characters (3认同)