Работа с JSON в C#: применение невалидного JSON в C#

уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Статья «Работа с JSON в C#: применение невалидного JSON в C#» относится по большей части к .NET 5 и более поздним версиям. Однако, некоторые настройки сериализатора JSON применимы и в .NET Core 3.1

Что касается веб-технологий, то здесь, в отличие от того же C# с давних времен присутствует некий «плюрализм мнений» относительно того, что правильно, а что нет. Так, например, некоторое время назад (да, похоже, и сейчас) не считается чем-то проблемным «забыть» какой-нибудь закрывающий html-тег в разметке страницы — браузер сам «разрулит» проблему. Не стал исключением в этом плане и формат JSON. Например, вы можете встретить такие «стандартные» невалидные JSON-объекты у которых числа записаны в кавычках, или объект заканчивается запятой («},») или же в объекте содержатся комментарии, которые, по-хорошему, вообще не должны присутствовать в JSON. Разработчики System.Text.Json предусмотрели подобные моменты при разработке классов для работы с JSON в C# и усовершенствовали их работу в .NET 5.

Пример невалидного JSON-объекта для работы

Допустим, мы разрабатываем приложение для работы с API какого-нибудь сервера в Сети. Естественно, что мы никак не можем повлиять на то, в какой форме этот сервер нам отвечает, а отвечает он нам на очередной запрос вот таким JSON-объектом:

{
  "Login": "Uasya", //логин
  "Password": "qwerty", //это пароль
  "Name": "Вася",
  "PersonFamily": "Пупкин",
  "Age": "38", //возраст
  "Birthday": "1983-01-16T00:00:00"
}

Здесь сразу три проблемы, которые не позволят нам десериализовать этот JSON в объект C#:

  1. Комментарии в JSON
  2. Числовое значение (возраст) записано как строка

Попытка десериализовать такой JSON в объект:

public class Person
{ 
    public string Name { get; set; }
    [JsonPropertyName("PersonFamily")]
    public string Surname { get; set; }
    public int age;
    public int Age //теперь свойство Age не будет сериализоваться
    { 
        get => age;
        set
        {
            if ((value < 0) || (value > 100))
                throw new Exception("Возраст должен находится в интервале от 0 до 100 лет");
            else
                age = value;
        }
    }
    public DateTime Birthday { get; set; }

    public Person(string name)
    {
        Name = name;
    }

    public Person()
    { }
}

приведет к исключению:

System.Text.Json.JsonException: «‘/’ is an invalid start of a property name. Expected a ‘»‘. Path: $ | LineNumber: 1 | BytePositionInLine: 20.»

Разрешить использовать такой JSON в своем приложении нам помогут настройки сериализации.

Разрешаем использовать невалидный JSON в C#

Настроим десериализацию объекта следующим образом:

JsonSerializerOptions options = new JsonSerializerOptions()
{
    WriteIndented = true,
    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,//не экранирем символы
    ReadCommentHandling = JsonCommentHandling.Skip, //комментарии в JSON пропускаем
    NumberHandling = JsonNumberHandling.AllowReadingFromString //разрешаем читать числа из строк
};

Теперь попробуем десериализовать объект. Получим следующий результат:

Имя: Вася
Фамилия: Пупкин
Возвраст: 38
День рождения: 16.01.1983 0:00:00
Настройка NumberHandling появилась только в .NET 5. В .NET Core 3.1 такой настройки нет

Итого

Сериализатор JsonSerializer позволяет десериализировать JSON-объекты, которые формально можно считать невалидными (содержащими ошибки). Для десериализации таких объектов можно воспользоваться настройками сериализатора ReadCommentHandling и NumberHandling.

уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
guest
0 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии