ядро dotnet System.Text.Json unescape unicode string

С помощью 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;}
}

создаст строку {"Name":"\u4F60\u597D"} но я хочу {"Name":"你好"}

Я создал фрагмент кода на https://dotnetfiddle.net/w73vnO, пожалуйста, помогите мне.

4 ответа

Решение

Вам необходимо установить параметры JsonSerializer, чтобы эти строки не кодировались.

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

Затем вы передаете эти параметры, когда звоните своему Serialize метод.

var s = JsonSerializer.Serialize(a, jso);        

Полный код:

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);

Результат:

Если вам нужно распечатать результат в консоли, вам может потребоваться установить дополнительный язык. Пожалуйста, обратитесь сюда.

Чтобы изменить поведение экранирования JsonSerializer вы можете передать обычай JavascriptEncoder к JsonSerializer установив Encoder собственность на JsonSerializerOptions.

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

Поведение по умолчанию разработано с учетом требований безопасности и 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);

Это сохраняет определенные меры безопасности, например, символы, чувствительные к HTML, будут по-прежнему экранированы.

Я бы предостерегал от использования System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscapingлегкомысленно, поскольку у него минимальное экранирование (поэтому в названии есть слово "небезопасно"). Если JSON, который вы создаете, записан в файл с кодировкой UTF-8 на диске или если его часть веб-запроса явно устанавливает кодировку в utf-8 (и не будет потенциально встроена в компонент HTML как есть), тогда, вероятно, можно использовать это.

См. Раздел примечаний в документации API:https://docs.microsoft.com/en-us/dotnet/api/system.text.encodings.web.javascriptencoder.unsaferelaxedjsonescaping?view=netcore-3.0

Вы также можете указать UnicodeRanges.Allесли вы ожидаете / хотите, чтобы все языки оставались без экранирования. Это по-прежнему позволяет избежать некоторых символов ASCII, которые подвержены уязвимостям безопасности.

JsonSerializerOptions options = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
};

Дополнительные сведения и примеры кода см. На https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to?view=netcore-3.0.

См. Предупреждение

Use:

      JsonSerializerOptions options = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
};

Ты можешь использовать: System.Text.RegularExpressions.Regex.Unescape(string)для отмены экранирования символов Юникода. https://docs.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex.unescape

Пример обновления из исходного вопроса:

      using System;
using System.Text.Json;

public class Program
{
    public static void Main()
    {
            var a = new A{Name = "你好"};
            var s = JsonSerializer.Serialize(a);
        
            var unescaped = System.Text.RegularExpressions.Regex.Unescape(s);

            Console.WriteLine(s);
            Console.WriteLine(unescaped);
        }
}

class A {
    public string Name {get; set;}
}

Выход:

      {"Name":"\u4F60\u597D"}
{"Name":"你好"}
Другие вопросы по тегам