Обработка недопустимых символов UTF-16 с помощью System.Text. Json .JsonSerializer - PullRequest
3 голосов
/ 29 января 2020

Я пытаюсь десериализовать строку JSON в объект, используя System.Text.Json.JsonSerializer. Иногда JSON, который я пытаюсь десериализовать, содержит недопустимые символы UTF-16. Например, символ \udcbf невозможно десериализовать в строку UTF-16. Я пытался следовать рекомендациям здесь для настройки кодировки символов, но, похоже, это относится исключительно к сериализации.

do tnet fiddle , чтобы показать проблему , Обратите внимание, что я использую кодировщик JSON, который поддерживает все символы Юникода от 0x0000 до 0xFFFF. Этот диапазон охватывает 0xDCBF, что позволяет мне полагать, что указанный кодировщик не используется для десериализации.

Одна вещь, которую я попытался сделать, это написать собственный преобразователь для обработки этих недопустимых символов:

public class InvalidUtf16Converter : JsonConverter<string>
{
    public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        try
        {
            return reader.GetString();
        }
        catch (InvalidOperationException)
        {
            var bytes = reader.ValueSpan;
            var sb = new StringBuilder(bytes.Length);
            foreach (var b in bytes)
                sb.Append(Convert.ToChar(b));
            return sb.ToString();
        }
    }

    public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) =>
        writer.WriteStringValue(value);
}

Этот подход своего рода работает (фактически не читает его в символ) для строковых свойств, как видно здесь . К сожалению, у меня иногда есть недопустимые символы UTF-16 в списках. В этом случае предоставленный конвертер не работает, как видно здесь , поскольку конвертер пытается преобразовать список в строку, которая по понятным причинам разбивается.

Существует ли способ глобальной обработки недопустимые символы UTF-16 при десериализации с использованием System.Text.Json? Если нет, то как бы написать конвертер, похожий на приведенный выше для списка?

...