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

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

  • автор:

 

Introduction to System.Text.Json Through Examples

Introduction to System.Text.Json Through Examples

In this article, we are going to learn about the System.Text.Json library that helps us efficiently and easily handle JSON in our applications.

Introduction

Starting from ASP.NET Core 3.0. the new System.Text.Json library has been shipped with the framework, and it’s only getting better over time. The library comes integrated with the latest version of the .NET framework, so it helps to eliminate outside dependencies for handling JSON. It’s a lightweight library that focuses on simple functionality and performance.

What Is JSON?

JSON or JavaScript Object Notation – is a way to format data that uses a specific attribute-value syntax, which makes it pretty intuitive and human-readable. It’s widely used on the internet to transfer and represent information, especially as a part of HTTP requests and responses. It stores attribute-value pairs, arrays, and other arbitrarily defined types of objects.

Most Important Features of the System.Text.Json Library

Before we start with examples, let’s have a quick overview of the library’s most important features.

Serialization and Deserialization

The System.Text.Json serializer and deserializer are built-in to the framework, and they are used, by default, when we are sending HTTP requests and responses with Web APIs. Of course, if we would like to customize our conversions, the library offers a few ways to do it:

  1. JsonSerializer Class – In this class, we can find exactly what we would expect – all the tools necessary to easily serialize and deserialize JSON with methods such as Serialize() , Deserialize() , SerializeAsync() etc.
  2. JsonDocument Class – This class is a great tool for both reading and writing JSON. It gives us the ability to create an in-memory read-only Document Object Model (DOM), which provides random access to objects in a JSON payload. We can use this class to write to a new JSON document comprised of cherry-picked elements from another JSON document
  3. Utf8JsonWriter / Utf8JsonReader classes – These are the classes that lie beneath the library’s straightforward serializer and deserializer. We can also use them as conversion methods if we want even more control over the process

Attributes

With System.Text.Json, we get a lot of different useful attributes. They mark our class properties so that they can get processed in specific ways during serialization and deserialization. Some examples are the [JsonIgnore] and [JsonPropertyName] attributes that we can use to modify the JSON conversion to exclude a certain class property or give it a different name.

JsonSerializerOptions

The library offers specific customization that can be set using the JsonSerializerOptions. With this class, we can set certain rules like using pretty print, making camel case the default JSON attribute name format, etc.

HttpClient Extensions

The library also works as the bottom layer of the System.Net.Http.Json library’s extension methods. They are used to serialize and deserialize JSON documents when we are using the HttpClient class in our projects.

Exploring Serialization with System.Text.Json

To see the System.Text.Json serializer and deserializer in action, let’s create a simple Console application.

Project Setup

To start, let’s create a new Console application project using Visual Studio.

After naming our project, and choosing a location, make sure to choose the latest version of the .NET framework in the Additional Information section.

Since the library already comes integrated with the framework, there is no need for any additional work and we can simply start exploring.

To start, let’s first create two simple classes:

We create two POCO classes – Person and Pet. The Person class has three properties: Name , Age and StateOfOrigin , and a list of pets, while the Pet class has properties Type , Name , and Age .

We create a new method called SerializeExample() . Inside it, we instantiate an array of objects of class Pet and assign them some values. We also instantiate an object of the Person class with some generic values, including the array of pets.

Then, we pass our newly created object right into the Serialize() method for processing, as the only mandatory parameter.
Besides this, we can also use the Serialize<Tvalue>() method that takes a value specified by the generic type parameter.

When we start our application and call SerializeExample() from our Main method, we can observe the results of both serialization method calls:

serializer-console-output

As we can see, the outputs of the two method calls are the same, but that is a pretty messy format of our JSON. We can change that to be more readable by setting some JsonSerializerOptions . We will learn more about those in the part where we explore the options functionality.

Besides these two methods, we can also use SerializeAsync() , which could be more common in REST APIs.

We can also use this method, for example, to write our JSON asynchronously to a file:

Of course, we also have to change the signature of the Main method to support async actions:

Now, we can start our application again:

serialize-to-file-console-output

The JSON content written in the file stays the same as before even though we took a slightly different route.

Exploring Deserialization with System.Text.Json

Deserialization works in a pretty similar way. We can use the deserialization methods from the same namespace, with or without the generic type parameter, but instead of the object instance, we will provide them with a JSON string:

We create a new method called DeserializeExample() . In the method body, we create a string variable and load it with JSON text. We can use the same text that we got as our output during serialization to make it easier.
Then, we deserialize the string using the Deserialize<Tvalue>() method and save that result into the personObject variable. After the deserialization, we print out some properties of our object.

Let’s call the DeserializeExample() method from our Main method and start the application:

Let’s modify our Program class again:

We create a new method called DeserializeWithJsonDocument() . In the method body, we first add a new JSON string. There isn’t a class defined in our code that directly matches the JSON data.
We use the JsonDocument class Parse() method, to parse this string into a JsonDocument type.
We can use this new type to extract, for example, the product name from the list of attributes.

For this, we use the RootElement property and then sequentially the GetProperty() method. We make sure to specify the property name which we want to locate. The extracted product name is now a JsonElement type and we can print it out easily.

To access a nested property, for example, the names of all the areas contained inside the Categories array – we extract the categories using the same approach as for the product name. Only in this case, we enumerate the categories as an array. We do this so we can loop over its JsonElements for easy access to the Area attributes.

Make sure to call this method from the Main method, and let’s start the application:

deserialization-json-document-console-output

We successfully cherry-picked our product name and the categories it belongs to!

Options for Serialization and Deserialization Actions

So we’ve learned how to serialize and deserialize our objects easily. Let’s now talk a bit more about options that help us customize our JSON reading and writing experience.

WriteIndented Property

If you remember our first printed output, it was a bit of a mess. Let’s fix that with the help of options:

In our new method SerializeWithOptions() , we have the same object instantiation as before, but we also create an instance of the JsonSerializerOptions class. In the new options object, we set the WriteIdented property to true. We take this options object and pass it as a second parameter to our Serialize() method.

Now let’s call the new SerializeWithOptions() method and check our results again:

deserialization-with-options-console-output

That’s a much nicer format of the same JSON text ��

Now, during instantiation, we set the Age property of our Person object to null. We also add the DefaultIgnoreCondition property to our options and set it to JsonIgnoreCondition.WhenWritingNull .

We can start our application one more time:

deserialization-ignore-nulls-console-output

In the output, we can see that our person no longer has the age property serialized, which is exactly what we wanted.

Deserializing Numbers in Quotation Marks

Lastly, let’s see how we can pass options to our deserializer method, to allow it to deserialize numbers when they are written in quotation marks.

Let’s create a new deserialization method:

We pass our options to the deserializer, along with the JSON string, and then print out some properties of our new object.

Of course, this is if you want to explicitly specify your options.

But, there is something called Web defaults for JsonSerializerOptions. It contains several properties set to their default values:

  • PropertyNameCaseInsensitive = true
  • JsonNamingPolicy = CamelCase
  • NumberHandling = AllowReadingFromString

As you can see, we can use these default options by just using a different JsonSerializerOptions constructor overload:

Now, we can call the new DeserializeWithOptions() method and start our application:

deserialization-with-options-console-output

As expected, our numbers in quotation marks have been deserialized correctly.

When we run our application we can use swagger to send a GET request to our endpoint:

test-controller-get-endpoint

We can see our familiar result in the response body.

Exploring System.Text.Json Attributes

Sometimes we want to deal with JSON documents that don’t follow our naming conventions, or we need to write a property name to a JSON document, that differs from the one defined in our class.

The [JsonPropertyName] attribute is very helpful in these cases so let’s see how we can use it.

First, we are going to modify our Person class:

An important step is to add the System.Text.Json.Serialization namespace, so that we can use the attributes. We assign the [JsonPropertyName] attribute to each property of the class. Then, by using the attribute, we set the property name to something different than it is in the class definition. Specifically, here we set all property names to lowercase, and change the StateOfOrigin property name to “state of origin”.

Let’s now start the application again, and send a GET request to our endpoint:

test-controller-get-endpoint-using-attributes

 

To see how it works, let’s modify our Pet class:

We also have to add the serialization namespace first, to be able to use this attribute. We decorate the Age property with the [JsonIgnore] attribute.

Let’s restart our application and send another GET request to our endpoint:

test-controller-get-endpoint-jsonignore

As expected, the age of the persons’ pets is no longer visible in our JSON output. We can do this for any class property we’d like.

Exploring System.Text.Json HttpClient Extensions

System.Text.Json library can also make our life easier in situations when we are using HttpClient. It works in the background of the System.Net.Http.Json namespace as a part of certain extension methods that perform automatic serialization and deserialization.

Or the Program class, if you are using .NET 6 and above:

We add the HttpClient service inside our ConfigureServices() method. The name “TestClientController” is going to represent our new controller that will mimic our client API. We also set the base address of our target API using options. Since this URI is specific to our example application, make sure to modify it to suit your specific localhost address.

If you want to learn more about using ASP.NET Core with HttpClient, feel free to read our article about it.

Using System.Text.Json HttpClient Extension Methods

To see how the extension methods work, we are going to create a new test client controller:

In our new controller, we inject the IHttpClientFactory in the constructor so that we can instantiate an HttpClient.
We add one new endpoint called GetJson() which creates an HttpClient instance using the CreateClient() method, with the client name as the parameter. This will automatically set the base address as we specified in the Startup class.

For the return value, we use the extension method GetFromJsonAsync<Tvalue>() , to which we provide the target endpoint name. Our test client controller shares the same Person class as our URI-defined endpoint, so we also provide that as the generic type parameter.

Now, let’s start the application and make a GET request to our new endpoint:

test-client-controller-get-endpoint

We can see that when we call the TestClient endpoint, we get the correct result returned from our original TestController endpoint. Behind the scenes, the return value from the endpoint was deserialized from the response body by the System.Text.Json library.

The other extension methods in this namespace include PostAsJsonAsync() and PutAsJsonAsync() .

Conclusion

In this article, we’ve covered the essentials of what is possible with the System.Text.Json library through code examples. We’ve learned about serialization, deserialization, different serializer options, attributes, and HttpClient extensions.

The basic building blocks are here, and you can start exploring the rest in your projects. Have fun!

Json does not exist in the namespace System

I’ve added System.Runtime.Serialization a reference but still cannot find System.Json.

Am I reading the Microsoft docs wrong? (I’m using .NET 4.5)

5 Answers 5

If you have questions on how to add enter nuget code, please follow the link below: http://docs.nuget.org/docs/start-here/using-the-package-manager-console

Most likely you are missing a reference to System.ServiceModel.Web

Make sure your application is targeting the .Net 4.5 framework in the project properties.

The System.Json objects are only available in 4.5

Use Nuget to install system.json : ‘Install-Package System.Json’

The Json object works only from Controller class and not outside. Even if we refer System.Web.MVC outside controller, we have access only to JsonResult and not to Json as Json object is protected object of JsonResult. Please refer the below documentation which explains that,

If you want to use other .Net json serializer, you can use the following:

Scott Hanselman

System.Text.Json and new built-in JSON support in .NET Core

In a world where JSON (JavaScript Object Notation) is everywhere it’s long been somewhat frustrating that .NET didn’t have built-in JSON support. JSON.NET is great and has served us well but it’s remained a 3rd party dependency for basic stuff like an ASP.NET web site or a simple console app.

Back in 2018 plans were announced to move JSON into .NET Core 3.0 as an intrinsic supported feature, and while they’re at it, get double the performance or more with Span<T> support and no memory allocations. ASP.NET in .NET Core 3.0 removes the JSON.NET dependency but still allows you to add it back in a single line if you’d like.

NOTE: This is all automatic and built in with .NET Core 3.0, but if you’re targeting .NET Standard or .NET Framework. Install the System.Text.Json NuGet package (make sure to include previews and install version 4.6.0-preview6.19303.8 or higher). In order to get the integration with ASP.NET Core, you must target .NET Core 3.0.

It’s very clean as well. Here’s a simple example.

The default options result in minified JSON as well.

Of course, when you’re returning JSON from a Controller in ASP.NET it’s all automatic and with .NET Core 3.0 it’ll automatically use the new System.Text.Json unless you override it.

Here’s an example where we pull out some fake Weather data (5 randomly created reports) and return the array.

The application/json is used and JSON is returned by default. If the return type was just string, we’d get text/plain. Check out this YouTube video to learn more details about System.Text.Json works and how it was designed. I’m looking forward to working with it more!

Sponsor: Get the latest JetBrains Rider with WinForms designer, Edit & Continue, and an IL (Intermediate Language) viewer. Preliminary C# 8.0 support, rename refactoring for F#-defined symbols across your entire solution, and Custom Themes are all included.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

Hosting By
Hosted in an Azure App Service

Работа с JSON в C#: сериализация и десериализация объектов

Формат JSON, в настоящее время, один из наиболее часто используемых текстовых форматов данных, используемых как для хранения информации об объектах, так и для обмена этой информацией по Сети. В свою очередь, сериализация JSON — это очень важный момент при разработке различных веб-приложений. И сегодня мы рассмотрим один из вариантов сериализации/десериализации объектов C# с использованием классов и объектов, расположенных в пространстве имен System.Text.Json . Этот сериализатор с момента выхода .NET Core 3 претерпел значительные изменения и показывает достаточно хорошие результаты тестов.

Что такое «сериализация»?

В соответствии с определением, данным Microsoft, сериализация — это процесс преобразования объекта в поток байтов для сохранения или передачи в память, базу данных или файл. Сериализация используется для того, чтобы сохранить состояния объекта для последующего воссоздания при необходимости. Обратный процесс называется десериализацией.

Например, при разработке приложений в Visual Studio , активно используются файлы в формате JSON, позволяющие сохранять настройки вашего приложения и восстанавливать эти настройки при запуске. Например, в C# вы можете сохранить (сериализовать) положение и размер главного окна приложения и при повторном запуске приложения восстановить (десериализовать) эти настройки объекта (главного окна приложения).

Для сериализации/десериализации JSON в C# можно использовать как штатный сериализатор JsonSerializer , расположенный в пространстве имен System.Text.Json , так и решения сторонних разработчиков, например, часто используемый JSON.NET. Мы будем использовать штатный сериализатор.

Пример сериализации и десериализации JSON

Допустим, у нас имеется вот такой класс для хранения информации о человеке:

Создадим объект этого класса и сохраним состояние объекта в файл в формате JSON:

Здесь мы выполнили следующие действия:

  1. Создали сам объект для сериализации ( person )
  2. Сериализовали объект в строку ( string ) используя сериализатор JsonSerializer
  3. Записали полученную строку в текстовый файл person.json .

Теперь рядом с exe-файлом приложения появился файл со следующим содержимым:

Теперь мы можем при следующем запуске программы восстановить (десериализовать) этот объект в нашей программе, например, так:

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

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

Для настройки сериализации мы можем передать в метод Serialize второй параметр — объект класса JsonSerializerOptions , который содержит настройки сериализации/десериализации объектов. Основные свойства этого класса следующие:

  • bool AllowTrailingCommas — устанавливает, надо ли добавлять после последнего элемента в json запятую. Если равно true , запятая добавляется
  • JsonNamingPolicy DictionaryKeyPolicy — возвращает или задает политику, используемую для преобразования имени ключа IDictionary в другой формат, например CamelCase.
  • JavaScriptEncoder Encoder — Возвращает или устанавливает кодировщик, используемый при экранировании строк. Укажите значение null для использования кодировщика по умолчанию
  • bool IgnoreNullValues — устанавливает, будут ли сериализоваться/десериализоваться в json объекты и их свойства со значением null
  • bool IgnoreReadOnlyProperties — аналогично устанавливает, будут ли сериализоваться свойства, предназначенные только для чтения
  • int MaxDepth — возвращает или задает максимальную глубину, разрешенную при сериализации или десериализации JSON, при этом значение по умолчанию 0 указывает максимальную глубину 64 .
  • bool PropertyNameCaseInsensitive — возвращает или задает значение, которое определяет, использует ли имя свойства сравнение без учета регистра во время десериализации. Значение по умолчанию — false .
  • JsonNamingPolicy PropertyNamingPolicy — возвращает или задает значение, указывающее политику, используемую для преобразования имени свойства объекта в другой формат, например CamelCase стиль, или null , чтобы оставить имена свойств без изменений.
  • JsonCommentHandling ReadCommentHandling — Возвращает или задает значение, определяющее, как комментарии обрабатываются во время десериализации
  • bool WriteIndented — устанавливает, будут ли добавляться в json пробелы (условно говоря, для красоты). Если равно true устанавливаются дополнительные пробелы

Рассмотрим несколько примеров использования этих настроек сериализации Json.

Как получить форматированную строку (с лидирующими пробелами) Json?

Для этого необходимо в настройках сериализации указать значение WriteIndented = true :

Как запретить экранировать строки при сериализации JSON?

В примере выше у нас все строки (имя, фамилия) экранированы. С точки зрения безопасности — это полностью правильное решение, но не всегда удобно для чтения. Чтобы позволить сериализатору не экранировать символы в строках мы можем воспользоваться свойством Encoder у JsonSerializerOptions следующим образом:

в этом случае, объект из примера выше будет выглядеть следующим образом:

Как сериализовать имена свойств в CamelCase?

По умолчанию, сериализация имен свойств объекта проводится как есть, однако, если вам необходимо применить к именам свойств стиль CamelCase (он же «верблюжий»), то можно использовать следующую настройку сериализации:

Теперь наш объект в JSON будет выглядеть следующим образом:

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

При сериализации/десериализации объектов в JSON бывает необходимым исключить какое-либо свойство из строки JSON. Например, в нашем объекте Person таким свойством может быть свойство Age , так как мы можем легко рассчитать возраст человека, зная его день рождения и каждый раз «таскать» это свойство в JSON — смысла нет. В этом случае нам может пригодиться настройка сериализации JSON с использованием атрибутов. Для того, чтобы воспользоваться таким видом настройки, необходимо подключить пространство имен System.Text.Json.Serialization .

Исключим свойство Age из сериализуемых, используя атрибут JsonIgnore :

Также, часто используемым атрибутом для настройки сериализации/десериализации JSON является атрибут JsonPropertyName , который позволяет задать произвольное имя сериализуемому свойству. Например,

Теперь свойство Surname будет сериализоваться в JSON с именем PersonFamily .

Особенности сериализации и десериализации JSON

При сериализации/десериализации JSON с использованием штатного сериализатора JsonSerializer необходимо обратить внимание на следующие моменты:

Десериализуемый объект должен иметь конструктор без параметров

Например, во всех примерах по работе с JSON в C# мы использовали конструктор по умолчанию. Если бы наш класс имел, например, только вот такой конструктор:

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

Сериализации подлежат только публичные свойства

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

Итого

Сегодня мы рассмотрели основные моменты того, как в C# происходит сериализация и десериализация объектов в JSON. Научились использовать настройки сериализации и десериализации с использованием атрибутов и специального класса JsonSerializerOptions . Конечно, возможности работы с JSON в C# этим не ограничиваются, но полученных знаний нам будет пока достаточно, чтобы попробовать использовать JSON в своих приложениях.

 

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

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