System text json c как подключить
Перейти к содержимому

System text json c как подключить

  • автор:

Как записать объекты .NET в формате JSON (сериализация)

В этой статье показано, как использовать System.Text.Json пространство имен для сериализации в нотации объектов JavaScript (JSON). Если вы переносите существующий код из Newtonsoft.Json , ознакомьтесь со статьей Переход с Newtonsoft.Json на System.Text.Json System.Text.Json .

Чтобы записать JSON в строку или в файл, вызовите метод JsonSerializer.Serialize.

В следующем примере показано создание JSON в виде строки:

using System.Text.Json; namespace SerializeBasic < public class WeatherForecast < public DateTimeOffset Date < get; set; >public int TemperatureCelsius < get; set; >public string? Summary < get; set; >> public class Program < public static void Main() < var weatherForecast = new WeatherForecast < Date = DateTime.Parse("2019-08-01"), TemperatureCelsius = 25, Summary = "Hot" >; string jsonString = JsonSerializer.Serialize(weatherForecast); Console.WriteLine(jsonString); > > > // output: //
Dim jsonString As String 

Выходные данные JSON минифицируются (пробелы, отступы и новые символы строки удаляются) по умолчанию.

В примере ниже для создания JSON-файла используется синхронный код:

using System.Text.Json; namespace SerializeToFile < public class WeatherForecast < public DateTimeOffset Date < get; set; >public int TemperatureCelsius < get; set; >public string? Summary < get; set; >> public class Program < public static void Main() < var weatherForecast = new WeatherForecast < Date = DateTime.Parse("2019-08-01"), TemperatureCelsius = 25, Summary = "Hot" >; string fileName = "WeatherForecast.json"; string jsonString = JsonSerializer.Serialize(weatherForecast); File.WriteAllText(fileName, jsonString); Console.WriteLine(File.ReadAllText(fileName)); > > > // output: //
jsonString = JsonSerializer.Serialize(weatherForecast1) File.WriteAllText(fileName, jsonString) 

В следующем примере для создания JSON-файла используется асинхронный код:

using System.Text.Json; namespace SerializeToFileAsync < public class WeatherForecast < public DateTimeOffset Date < get; set; >public int TemperatureCelsius < get; set; >public string? Summary < get; set; >> public class Program < public static async Task Main() < var weatherForecast = new WeatherForecast < Date = DateTime.Parse("2019-08-01"), TemperatureCelsius = 25, Summary = "Hot" >; string fileName = "WeatherForecast.json"; await using FileStream createStream = File.Create(fileName); await JsonSerializer.SerializeAsync(createStream, weatherForecast); Console.WriteLine(File.ReadAllText(fileName)); > > > // output: //
Dim createStream As FileStream = File.Create(fileName) Await JsonSerializer.SerializeAsync(createStream, weatherForecast1) 

В предыдущих примерах для сериализуемого типа используется определение типа. Перегрузка Serialize() принимает параметр универсального типа:

using System.Text.Json; namespace SerializeWithGenericParameter < public class WeatherForecast < public DateTimeOffset Date < get; set; >public int TemperatureCelsius < get; set; >public string? Summary < get; set; >> public class Program < public static void Main() < var weatherForecast = new WeatherForecast < Date = DateTime.Parse("2019-08-01"), TemperatureCelsius = 25, Summary = "Hot" >; string jsonString = JsonSerializer.Serialize(weatherForecast); Console.WriteLine(jsonString); > > > // output: //
jsonString = JsonSerializer.Serialize(Of WeatherForecastWithPOCOs)(weatherForecast) 

Поведение сериализации

  • По умолчанию все открытые свойства сериализуются. Вы можете указать свойства, которые нужно игнорировать. Вы также можете включить частные члены.
  • Кодировщик по умолчанию экранирует символы, не относящиеся к ASCII, символы, учитывающие HTML, в пределах диапазона ASCII и символы, которые должны быть экранированы в соответствии со спецификацией JSON RFC 8259.
  • По умолчанию JSON сокращается. Вы можете структурировать JSON.
  • По умолчанию регистр имен JSON соответствует именам в .NET. Вы можете настроить регистр имен JSON.
  • По умолчанию обнаруживаются циклические ссылки и создаются исключения. Вы можете сохранять ссылки и обрабатывать циклические ссылки.
  • По умолчанию поля игнорируются. Вы можете включить поля.

При косвенном использовании System.Text.Json в приложении ASP.NET Core некоторые поведения по умолчанию отличаются. Дополнительные сведения см. в разделе Стандартные параметры веб-приложений для JsonSerializerOptions.

К поддерживаемым типам относятся:

  • Примитивы .NET, которые сопоставляются с примитивами JavaScript, например числовыми типами, строками и логическими значениями.
  • Определяемые пользователем объекты POCO (традиционные объекты среды CLR).
  • Одномерные массивы и массивы массивов ( T[][] ).
  • Коллекции и словари из следующих пространств имен:
    • System.Collections
    • System.Collections.Generic
    • System.Collections.Immutable
    • System.Collections.Concurrent
    • System.Collections.Specialized
    • System.Collections.ObjectModel

    Для обработки дополнительных типов или для обеспечения функциональности, которая не поддерживается встроенными преобразователями, можно реализовать пользовательские преобразователи.

    Ниже приведен пример, показывающий, как класс, содержащий свойства коллекции, и определяемый пользователем тип сериализуется:

    using System.Text.Json; namespace SerializeExtra < public class WeatherForecast < public DateTimeOffset Date < get; set; >public int TemperatureCelsius < get; set; >public string? Summary < get; set; >public string? SummaryField; public IList? DatesAvailable < get; set; >public Dictionary? TemperatureRanges < get; set; >public string[]? SummaryWords < get; set; >> public class HighLowTemps < public int High < get; set; >public int Low < get; set; >> public class Program < public static void Main() < var weatherForecast = new WeatherForecast < Date = DateTime.Parse("2019-08-01"), TemperatureCelsius = 25, Summary = "Hot", SummaryField = "Hot", DatesAvailable = new List() < DateTime.Parse("2019-08-01"), DateTime.Parse("2019-08-02") >, TemperatureRanges = new Dictionary < ["Cold"] = new HighLowTemps < High = 20, Low = -10 >, ["Hot"] = new HighLowTemps < High = 60 , Low = 20 >>, SummaryWords = new[] < "Cool", "Windy", "Humid" >>; var options = new JsonSerializerOptions < WriteIndented = true >; string jsonString = JsonSerializer.Serialize(weatherForecast, options); Console.WriteLine(jsonString); > > > // output: //< // "Date": "2019-08-01T00:00:00-07:00", // "TemperatureCelsius": 25, // "Summary": "Hot", // "DatesAvailable": [ // "2019-08-01T00:00:00-07:00", // "2019-08-02T00:00:00-07:00" // ], // "TemperatureRanges": < // "Cold": < // "High": 20, // "Low": -10 // >, // "Hot": < // "High": 60, // "Low": 20 // >// >, // "SummaryWords": [ // "Cool", // "Windy", // "Humid" // ] //> 
    Public Class WeatherForecastWithPOCOs Public Property [Date] As DateTimeOffset Public Property TemperatureCelsius As Integer Public Property Summary As String Public SummaryField As String Public Property DatesAvailable As IList(Of DateTimeOffset) Public Property TemperatureRanges As Dictionary(Of String, HighLowTemps) Public Property SummaryWords As String() End Class Public Class HighLowTemps Public Property High As Integer Public Property Low As Integer End Class ' serialization output formatted (pretty-printed with whitespace and indentation): ' < ' "Date": "2019-08-01T00:00:00-07:00", ' "TemperatureCelsius": 25, ' "Summary": "Hot", ' "DatesAvailable": [ ' "2019-08-01T00:00:00-07:00", ' "2019-08-02T00:00:00-07:00" ' ], ' "TemperatureRanges": < ' "Cold": < ' "High": 20, ' "Low": -10 ' >, ' "Hot": < ' "High": 60, ' "Low": 20 ' >' >, ' "SummaryWords": [ ' "Cool", ' "Windy", ' "Humid" ' ] ' > 

    Сериализация в UTF-8

    Это 5-10 % быстрее сериализовать в массив байтов UTF-8, чем использовать строковые методы. Это связано с тем, что байты (как UTF-8) не нужно преобразовать в строки (UTF-16).

    Чтобы сериализовать массив байтов UTF-8, вызовите JsonSerializer.SerializeToUtf8Bytes метод:

    byte[] jsonUtf8Bytes =JsonSerializer.SerializeToUtf8Bytes(weatherForecast); 
    Dim jsonUtf8Bytes As Byte() Dim options As JsonSerializerOptions = New JsonSerializerOptions With < .WriteIndented = True >jsonUtf8Bytes = JsonSerializer.SerializeToUtf8Bytes(weatherForecast1, options) 

    Также доступна перегрузка Serialize, которая принимает Utf8JsonWriter.

    Сериализация в форматированный JSON

    Чтобы структурировать выходные данные JSON, задайте для JsonSerializerOptions.WriteIndented значение true .

    using System.Text.Json; namespace SerializeWriteIndented < public class WeatherForecast < public DateTimeOffset Date < get; set; >public int TemperatureCelsius < get; set; >public string? Summary < get; set; >> public class Program < public static void Main() < var weatherForecast = new WeatherForecast < Date = DateTime.Parse("2019-08-01"), TemperatureCelsius = 25, Summary = "Hot" >; var options = new JsonSerializerOptions < WriteIndented = true >; string jsonString = JsonSerializer.Serialize(weatherForecast, options); Console.WriteLine(jsonString); > > > // output: // < // "Date": "2019-08-01T00:00:00-07:00", // "TemperatureCelsius": 25, // "Summary": "Hot" //>
    Dim options As JsonSerializerOptions = New JsonSerializerOptions With < .WriteIndented = True >jsonString = JsonSerializer.Serialize(weatherForecast, options) 

    При многократном использовании JsonSerializerOptions с одинаковыми параметрами не создавайте новый экземпляр JsonSerializerOptions при каждом использовании. Повторно используйте один и тот же экземпляр для каждого вызова. Дополнительные сведения см. в разделе Повторное использование экземпляров JsonSerializerOptions.

    Совместная работа с нами на GitHub

    Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.

    Не могу подключить using System.Text.Json

    Author24 — интернет-сервис помощи студентам

    Всем утро доброе.
    не могу подключить using System.Text.Json
    может у кого-то были такие же проблемы.
    «не существует в пространстве имен,возможно нет ссылки на сборку» в общем, как обычно)
    Ссылку я подключил

    Лучшие ответы ( 1 )
    94731 / 64177 / 26122
    Регистрация: 12.04.2006
    Сообщений: 116,782
    Ответы с готовыми решениями:

    Не могу подключить к проекту ссылку на System.Runtime.Serialization.Formatters.Binary
    Столкнулся с непонятной проблемой. Не могу подключить к проекту ссылку на.

    Пространство имен и System.Text.Json
    При написании строки "using System.Text.Json;" выделяет "Json" и пишет "Имя типа или пространства.

    Не могу подключить к WPF пространство System.Windows
    Добрый день. Нужно поюзать таймер в WPF приложении. Дела вот так: /// <summary> .

    Администратор

    Эксперт .NET

    16746 / 13156 / 5155
    Регистрация: 17.03.2014
    Сообщений: 26,825
    Записей в блоге: 1

    Лучший ответ

    Сообщение было отмечено Anton006 как решение

    Решение

    Anton006, это пространство имен появилось в .NET Core 3.0. У тебя точно проект под этот фреймворк? Если нет, то используй библиотеку Json.NET.

    Регистрация: 24.04.2020
    Сообщений: 1

    Столкнулся с этой же проблемой, решил ее так:
    1) Поставил себе .NET Framework 4.7.2 (брать на сайте микромягких, пак для разработчиков нужен https://dotnet.microsoft.com/d. m=referral ).
    2) Поменял в свойствах проекта целевую платформу на .NET Framework 4.7.2 (ПКМ на ConsoleApp — Свойства — приложение — Целевая платформа)
    3) Скачал пакет System.Text.Json (меню Проект — Управление пакетами NuGet. Далее Обзор — и в поиск System.Text.Json)
    После чего все заработало

    87844 / 49110 / 22898
    Регистрация: 17.06.2006
    Сообщений: 92,604
    Помогаю со студенческими работами здесь

    Convert JSON to Text
    Как на VB написать подобный конвектор для преобразования json в текст.

    Или воспользуйтесь поиском по форуму:

    Работа с JSON

    JSON (JavaScript Object Notation) является одним из наиболее популярных форматов для хранения и передачи данных. И платформа .NET предоставляет функционал для работы с JSON.

    Основная функциональность по работе с JSON сосредоточена в пространстве имен System.Text.Json . Ключевым типом является класс JsonSerializer , который и позволяет сериализовать объект в json и, наоборот, десериализовать код json в объект C#.

    Для сохранения объекта в json в классе JsonSerializer определен статический метод Serialize() и его асинхронный двойник SerializeAsyc() , которые имеют ряд перегруженных версий. Некоторые из них:

    • string Serialize(Object obj, Type type, JsonSerializerOptions options) : сериализует объект obj типа type и возвращает код json в виде строки. Последний необязательный параметр options позволяет задать дополнительные опции сериализации
    • string Serialize(T obj, JsonSerializerOptions options) : типизированная версия сериализует объект obj типа T и возвращает код json в виде строки.
    • Task SerializeAsync(Stream utf8Json, Object obj, Type type, JsonSerializerOptions options) : сериализует объект obj типа type и записывает его в поток utf8Json. Последний необязательный параметр options позволяет задать дополнительные опции сериализации
    • Task SerializeAsync(Stream utf8Json, T obj, JsonSerializerOptions options) : типизированная версия сериализует объект obj типа T в поток utf8Json.

    Для десериализации кода json в объект C# применяется метод Deserialize() и его асинхронный двойник DeserializeAsync() , которые имеют различные версии. Некоторые из них:

    • object? Deserialize(string json, Type type, JsonSerializerOptions options) : десериализует строку json в объект типа type и возвращает десериализованный объект. Последний необязательный параметр options позволяет задать дополнительные опции десериализации
    • T? Deserialize(string json, JsonSerializerOptions options) : десериализует строку json в объект типа T и возвращает его.
    • ValueTask DeserializeAsync(Stream utf8Json, Type type, JsonSerializerOptions options, CancellationToken token) : десериализует данные из потока utf8Json, который представляет объект JSON, в объект типа type. Последние два параметра необязательны: options позволяет задать дополнительные опции десериализации, а token устанавливает CancellationToken для отмены задачи. Возвращается десериализованный объект, обернутый в ValueTask
    • ValueTask DeserializeAsync(Stream utf8Json, JsonSerializerOptions options, CancellationToken token) : десериализует данные из потока utf8Json, который представляет объект JSON, в объект типа T. Возвращается десериализованный объект, обернутый в ValueTask

    Рассмотрим применение класса на простом примере. Сериализуем и десериализуем простейший объект:

    using System.Text.Json; Person tom = new Person("Tom", 37); string json = JsonSerializer.Serialize(tom); Console.WriteLine(json); Person? restoredPerson = JsonSerializer.Deserialize(json); Console.WriteLine(restoredPerson?.Name); // Tom class Person < public string Name < get;>public int Age < get; set; >public Person(string name, int age) < Name = name; Age = age; >>

    Здесь вначале сериализуем с помощью метода JsonSerializer.Serialize() объект типа Person в стоку с кодом json. Затем обратно получаем из этой строки объект Person посредством метода JsonSerializer.Deserialize() .

    Хотя в примере выше сериализовался/десериализовался объект класса, но подобным способом мы также можем сериализовать/десериализовать структуры.

    Некоторые замечания по сериализации/десериализации

    Объект, который подвергается десериализации, должен иметь либо конструктор без параметров, либо конструктор, для всех параметров которого в десериализуемом json-объекте есть значения (соответствие между параметрами конструктора и свойствами json-объекта устанавливается на основе названий, причем регистр не играет значения).

    Сериализации подлежат только публичные свойства объекта (с модификатором public).

    Запись и чтение файла json

    Поскольку методы SerializeAsyc/DeserializeAsync могут принимать поток типа Stream, то соответственно мы можем использовать файловый поток для сохранения и последующего извлечения данных:

    using System.Text.Json; // сохранение данных using (FileStream fs = new FileStream("user.json", FileMode.OpenOrCreate)) < Person tom = new Person("Tom", 37); await JsonSerializer.SerializeAsync(fs, tom); Console.WriteLine("Data has been saved to file"); > // чтение данных using (FileStream fs = new FileStream("user.json", FileMode.OpenOrCreate)) < Person? person = await JsonSerializer.DeserializeAsync(fs); Console.WriteLine($"Name: Age: "); > class Person < public string Name < get;>public int Age < get; set; >public Person(string name, int age) < Name = name; Age = age; >>

    В данном случае вначале данные сохраняются в файл user.json и затем считываются из него.

    Настройка сериализации с помощью JsonSerializerOptions

    По умолчанию JsonSerializer сериализует объекты в минимифицированный код. С помощью дополнительного параметра типа JsonSerializerOptions можно настроить механизм сериализации/десериализации, используя свойства JsonSerializerOptions. Некоторые из его свойств:

    • AllowTrailingCommas : устанавливает, надо ли добавлять после последнего элемента в json запятую. Если равно true , запятая добавляется
    • DefaultIgnoreCondition : устанавливает, будут ли сериализоваться/десериализоваться в json свойства со значениями по умолчанию
    • IgnoreReadOnlyProperties : аналогично устанавливает, будут ли сериализоваться свойства, предназначенные только для чтения
    • WriteIndented : устанавливает, будут ли добавляться в json пробелы (условно говоря, для красоты). Если равно true устанавливаются дополнительные пробелы
    using System.Text.Json; Person tom = new Person("Tom", 37); var options = new JsonSerializerOptions < WriteIndented = true >; string json = JsonSerializer.Serialize(tom, options); Console.WriteLine(json); Person? restoredPerson = JsonSerializer.Deserialize(json); Console.WriteLine(restoredPerson?.Name);

    Настройка сериализации с помощью атрибутов

    По умолчанию сериализации подлежат все публичные свойства. Кроме того, в выходном объекте json все названия свойств соответствуют названиям свойств объекта C#. Однако с помощью атрибутов JsonIgnore и JsonPropertyName .

    Атрибут JsonIgnore позволяет исключить из сериализации определенное свойство. А JsonPropertyName позволяет замещать оригинальное название свойства. Пример использования:

    using System.Text.Json; using System.Text.Json.Serialization; Person tom = new Person("Tom", 37); string json = JsonSerializer.Serialize(tom); Console.WriteLine(json); Person? person = JsonSerializer.Deserialize(json); Console.WriteLine($"Name: Age: "); class Person < [JsonPropertyName("firstname")] public string Name < get;>[JsonIgnore] public int Age < get; set; >public Person(string name, int age) < Name = name; Age = age; >>

    В данном случае свойство Age будет игнорироваться, а для свойства Name будет использоваться псевдоним «firstname». Консольный вывод:

     Name: Tom Age: 0

    Обратите внимание, что, поскольку свойство Age не было сериализовано, то при десериализации для него используется значение по умолчанию.

    System text json c как подключить

    JSON является распространенным форматом для передачи данных. Рассмотрим, как мы можем посылать и получить данные json.

    Отправка JSON. Метод WriteAsJsonAsync

    Для отправки json можно воспользоваться методом WriteAsJson()/WriteAsJsonAsync() объекта HttpResponse . Этот метод позволяет сериализовать переданные в него объекты в формат JSON и автоматически для заголовка «content-type» устанавливает значение «application/json; charset=utf-8»:

    var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.Run(async (context) => < Person tom = new("Tom", 22); await context.Response.WriteAsJsonAsync(tom); >); app.Run(); public record Person(string Name, int Age);

    В данном случае клиенту отправляется объект типа Person, который представляет класс-record, однако это может быть и обычный класс:

    Отправка json с помощью WriteAsJson в ASP.NET Core и C#

    Хотя можно было бы воспользоваться и стандартным методом WriteAsync() :

    app.Run(async (context) => < var response = context.Response; response.Headers.ContentType = "application/json; charset=utf-8"; await response.WriteAsync(""); >);

    Получение JSON. Метод ReadFromJsonAsync

    Для получения из запроса объект в формате JSON в классе HttpRequest определен метод ReadFromJsonAsync() . Он позволяет сериализовать данные в объект определенного типа.

    Например, создадим в проекте папку html , в которой определим новый файл index.html .

    Отправка объекта json на сервер ASP.NET Core в C#

    В файле index.html определим следующий код:

        METANIT.COM  

    User form

    Name:

    Age:

    Здесь по нажатию на кнопку с помощью функции fetch() по адресу «/api/user» будет отправляться объект со свойствами name и age, значения для которых берутся из полей формы. В ответ от сервера веб-страница также получает объект в формате json, в котором имеется свойство text — свойство, которое хранит сообщение от сервера.

    Теперь в файле Program.cs определим код для получения данных, отправляемых веб-страницей:

    var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.Run(async (context) => < var response = context.Response; var request = context.Request; if (request.Path == "/api/user") < var message = "Некорректные данные"; // содержание сообщения по умолчанию try < // пытаемся получить данные json var person = await request.ReadFromJsonAsync(); if (person != null) // если данные сконвертированы в Person message = $"Name: Age: "; > catch < >// отправляем пользователю данные await response.WriteAsJsonAsync(new < text = message >); > else < response.ContentType = "text/html; charset=utf-8"; await response.SendFileAsync("html/index.html"); >>); app.Run(); public record Person(string Name, int Age);

    В данном случае, если обращение идет по адресу «/api/user», то получаем данные в формате json. При обращениях по другим адресам просто посылаем веб-страницу index.html.

    Метода ReadFromJsonAsync() десериализует полученные данные в объект определенного типа — в данном случае типа Person:

    var person = await request.ReadFromJsonAsync(); if (person != null) // если данные сконвертированы в Person message = $"Name: Age: ";

    Таким образом, здесь результат вызова этого метода — значение переменной person будет представлять объект Person.

    Ноб стоит отметить, что если данные запроса не представляют объект JSON, либо если метод ReadFromJsonAsync() не смог связать данные запроса со свойствами класса Person, то вызов этого метода сгенерирует исключение. Поэтому в данном случае вызов метода помещается в конструкцию try..catch. Однако нельзя не отметить, что try..catch здесь является узким местом, и далее мы посмотрим, как от него избавиться.

    И в конце в ответ посылаем анонимный объект, который также сериализуется в json с некоторым сообщением, которое хранится в свойстве text. При получении этого сообщения оно выводится на веб-страницу.

    ReadFromJsonAsync и чтение данных json в ASP.NET Core и C#

    Стоит отметить, что проверять на наличие json в запросе можно с помощью метода HasJsonContentType() — он возвращает true , если клиент прислал json.

    if (request.HasJsonContentType()) < var person = await request.ReadFromJsonAsync(); if (person != null) responseText = $"Name: Age: "; >

    Настройка сериализации

    При получении данных в формате json мы можем столкнуться с рядом проблем. Хотя бы взять предыдущий пример, где мы вынуждены были помещать вызов метода ReadFromJsonAsync в конструкцию — try..catch. Например, если мы не введем в поля формы никаких значений, то стандартный механизм привязки значений не сможет связать данные запроса со свойством Age. И мы получим исключение.

    Аналогичный пример, когда данные json не совсем соответствуют определению типа, в который надо выполнить десериализацию:

    const response = await fetch("/api/user", < method: "POST", headers: < "Accept": "application/json", "Content-Type": "application/json" >, body: JSON.stringify(< userName: "Tom", userAge: 22 >) >);

    Здесь названия свойств отправляемого объекта не соответствуют названиям свойств типа Person в C#. Однако объект Person все равно будет создан, просто его свойства получат значения по умолчанию (null для свойства Name и 0 для свойства Age).

    Другой пример — отправляемые данные не соответствуют по типу:

    const response = await fetch("/api/user", < method: "POST", headers: < "Accept": "application/json", "Content-Type": "application/json" >, body: JSON.stringify(< name: "Tom", age: "twenty-two" >) >);

    Здесь свойство «age» представляет строку и не сможет быть сконвертировано в значение типа int . В итоге при отправке подобных данных на сервере возникнет исключение типа System.Text.Json.JsonException , а клиент получит информацию об исключении.

    В обоих выше приведенных примерах в зависимости от задачи можно использовать различные решения — обрабатывть исключения, встраивать дополнительные middleware для отлова подобных ситуаций и так далее. Одним из решений подобных проблем также может быть настройка сериализации/десериализации с помощью параметра типа JsonSerializerOptions , которое может передаваться в метод ReadFromJsonAsync()

    ReadFromJsonAsync(JsonSerializerOptions options);

    Так, изменим код файла Program.cs :

    using System.Text.Json; using System.Text.Json.Serialization; var builder = WebApplication.CreateBuilder(); var app = builder.Build(); app.Run(async (context) => < var response = context.Response; var request = context.Request; if (request.Path == "/api/user") < var responseText = "Некорректные данные"; // содержание сообщения по умолчанию if (request.HasJsonContentType()) < // определяем параметры сериализации/десериализации var jsonoptions = new JsonSerializerOptions(); // добавляем конвертер кода json в объект типа Person jsonoptions.Converters.Add(new PersonConverter()); // десериализуем данные с помощью конвертера PersonConverter var person = await request.ReadFromJsonAsync(jsonoptions); if (person != null) responseText = $"Name: Age: "; > await response.WriteAsJsonAsync(new ); > else < response.ContentType = "text/html; charset=utf-8"; await response.SendFileAsync("html/index.html"); >>); app.Run(); public record Person(string Name, int Age); public class PersonConverter : JsonConverter  < public override Person Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) < var personName = "Undefined"; var personAge = 0; while (reader.Read()) < if (reader.TokenType == JsonTokenType.PropertyName) < var propertyName = reader.GetString(); reader.Read(); switch (propertyName?.ToLower()) < // если свойство age и оно содержит число case "age" when reader.TokenType == JsonTokenType.Number: personAge = reader.GetInt32(); // считываем число из json break; // если свойство age и оно содержит строку case "age" when reader.TokenType == JsonTokenType.String: string? stringValue = reader.GetString(); // пытаемся конвертировать строку в число if (int.TryParse(stringValue, out int value)) < personAge = value; >break; case "name": // если свойство Name/name string? name = reader.GetString(); if(name!=null) personName = name; break; > > > return new Person(personName, personAge); > // сериализуем объект Person в json public override void Write(Utf8JsonWriter writer, Person person, JsonSerializerOptions options) < writer.WriteStartObject(); writer.WriteString("name", person.Name); writer.WriteNumber("age", person.Age); writer.WriteEndObject(); >>

    Поскольку настройка параметров сериализации/десериализации — это отдельная большая тема, то пройдемся вкратце по коду, который вовлекается в процесс конвертации и прежде всего по конвертеру Person в json.

    Определение конвертера для сериализации/десериализации объекта в json

    Класс конвертера для сериализации/десериализации объекта определенного типа в JSON должен наследоваться от класса JsonConverter . Абстрактный класс JsonConverter типизируется типом, для объекта которого надо выполнить сериализацию/десериализацию. В коде выше такой реализацией является класс PersonConverter .

    При наследовании класса JsonConverter необходимо реализовать его абстрактные методы Read() (выполняет десериализацию из JSON в Person) и Write() (выполняет сериализацию из Person в JSON).

    Метод Write, который записывает данные Person в формат JSON, выглядит относительно просто:

    public override void Write(Utf8JsonWriter writer, Person person, JsonSerializerOptions options)

    Он принимает три параметра:

    • Utf8JsonWriter — объект, который записывает данные в json
    • Person — объект, который надо сериализовать
    • JsonSerializerOptions — дополнительные параметры сериализации

    Сначала с помощью объекта Utf8JsonWriter открываем запись объекта в формате json:

    writer.WriteStartObject();

    Последовательно записываем данные объекта Person:

    writer.WriteString("name", person.Name); writer.WriteNumber("age", person.Age);

    И завершаем запись объекта:

    writer.WriteEndObject();

    Чтение или десериализация выглядит несколько сложнее. Метод Read() также принимает три параметра:

    • Utf8JsonReader — объект, который читает данные из json
    • Type — тип, в который надо выполнить конвертацию
    • JsonSerializerOptions — дополнительные параметры сериализации

    Результатом метода Read() должен быть десериализованный объект (в данном случае объект типа Person).

    В начале определяем данные объекта Person по умолчанию, которые будут применяться, если в процессе десериализации произойдут проблемы:

    var personName = "Undefined"; var personAge = 0;

    Далее в цикле считываем каждый токен в строке json с помощью метода Read() объекта Utf8JsonReader:

    while (reader.Read())

    Затем, если считанный токен представляет название свойства, то считываем его и считываем следующий токен:

    if (reader.TokenType == JsonTokenType.PropertyName) < var propertyName = reader.GetString(); reader.Read();

    После этого мы можем узнать, как называется свойство и какое значение оно имеет. Для этого применяем конструкцию switch :

    switch (propertyName?.ToLower()) 
    

    Посольку регистр символов название свойства может отличаться (например, "Age", "age" или "AGE"), то, чтобы упростить сравнение, приводим название свойства к нижнему регистру.

    Например, мы ожидаем, что json будет содержать свойство с именем "age", которое будет хранить некоторое число. Для его получения применяем следующий блок case:

    case "age" when reader.TokenType == JsonTokenType.Number: personAge = reader.GetInt32(); break;

    То есть если свойство называется "age" и представляет число (JsonTokenType.Number), то вызываем метод reader.GetInt32()

    Но свойство "age" также может содержать строку, например, "23". Такая строка может конвертироваться в число. И для подобного случая добавляем дополнительный блок case:

    case "age" when reader.TokenType == JsonTokenType.String: string? stringValue = reader.GetString(); if (int.TryParse(stringValue, out int value)) < personAge = value; >break;

    Подобным образом считываем из json значение для свойства Name:

    case "name": string? name = reader.GetString(); if(name!=null) personName = name;

    В конце полученными данными инициализируем объект Person и возвращаем его из метода:

    return new Person(personName, personAge);

    Таким образом, мы можем проверить, какие свойства имеет объект json, какие значения они несут и принять решения, передавать эти значения в объект Person. И в данном случае, даже если в присланном json не будет нужных свойств, или свойство age будет содержать строку, которая не конвертируется в число, объект Person все равно будет создан.

    Чтобы использовать конвертер json, его надо добавить в коллекцию конвертеров:

    var jsonoptions = new JsonSerializerOptions(); jsonoptions.Converters.Add(new PersonConverter()); var person = await request.ReadFromJsonAsync(jsonoptions);

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *