<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Theodoros Bebekis</title>
    <description>The latest articles on DEV Community by Theodoros Bebekis (@tbebekis).</description>
    <link>https://dev.to/tbebekis</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1711126%2F9a43edc2-8b17-4a3b-b80b-93fa344e16b1.png</url>
      <title>DEV Community: Theodoros Bebekis</title>
      <link>https://dev.to/tbebekis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tbebekis"/>
    <language>en</language>
    <item>
      <title>Fundamental Concepts of Business Applications II: The Locator Pattern</title>
      <dc:creator>Theodoros Bebekis</dc:creator>
      <pubDate>Sat, 04 Jul 2026 11:00:26 +0000</pubDate>
      <link>https://dev.to/tbebekis/fundamental-concepts-of-business-applications-ii-the-locator-pattern-3i0d</link>
      <guid>https://dev.to/tbebekis/fundamental-concepts-of-business-applications-ii-the-locator-pattern-3i0d</guid>
      <description>&lt;p&gt;In the previous article, we argued that a ComboBox is not enough.&lt;/p&gt;

&lt;p&gt;Not because there is anything wrong with the control itself, but because the problem it is designed to solve is much smaller than the actual problem faced by a business application.&lt;/p&gt;

&lt;p&gt;That, however, is where we stopped.&lt;/p&gt;

&lt;p&gt;We did not answer the next question.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If the problem is not selecting a value, then what exactly is it?&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;Let us put frameworks aside for a moment.&lt;/p&gt;

&lt;p&gt;Forget about controls.&lt;/p&gt;

&lt;p&gt;Forget even the word &lt;em&gt;Locator&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Imagine we are editing a line in a sales order.&lt;/p&gt;

&lt;p&gt;The user moves to the product field and types:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PROD-001&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What should happen next?&lt;/p&gt;

&lt;p&gt;The first answer seems obvious.&lt;/p&gt;

&lt;p&gt;"The product should be found."&lt;/p&gt;

&lt;p&gt;Agreed.&lt;/p&gt;

&lt;p&gt;But is that really enough?&lt;/p&gt;




&lt;p&gt;Let us assume the product has been found.&lt;/p&gt;

&lt;p&gt;Are we finished?&lt;/p&gt;

&lt;p&gt;Not at all.&lt;/p&gt;

&lt;p&gt;The application still does not know which sales price applies, which unit of measure should be used, which VAT rate is applicable, or even whether the item is currently available in stock.&lt;/p&gt;

&lt;p&gt;And in many cases, it must know even more.&lt;/p&gt;

&lt;p&gt;Perhaps a different pricing policy applies to this particular customer.&lt;/p&gt;

&lt;p&gt;Perhaps a different price list is currently active.&lt;/p&gt;

&lt;p&gt;Perhaps even the document date changes the result.&lt;/p&gt;

&lt;p&gt;This leads to the first truly interesting question.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where does all this information come from?&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;Suddenly, the product is no longer simply the product.&lt;/p&gt;

&lt;p&gt;It is the same product &lt;strong&gt;within a specific business context&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And that context is not an implementation detail.&lt;/p&gt;

&lt;p&gt;It is not an internal state maintained by whatever mechanism performs the resolution.&lt;/p&gt;

&lt;p&gt;It is an explicit input to the problem itself.&lt;/p&gt;




&lt;p&gt;There is another important observation.&lt;/p&gt;

&lt;p&gt;The user did not enter a ProductId.&lt;/p&gt;

&lt;p&gt;They did not enter a GUID.&lt;/p&gt;

&lt;p&gt;In fact, they are probably unaware that such an identifier even exists.&lt;/p&gt;

&lt;p&gt;They entered:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PROD-001&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In other words, they entered a business reference.&lt;/p&gt;

&lt;p&gt;This is perfectly natural.&lt;/p&gt;

&lt;p&gt;People do not think in terms of technical identifiers.&lt;/p&gt;

&lt;p&gt;They think in product codes.&lt;/p&gt;

&lt;p&gt;Names.&lt;/p&gt;

&lt;p&gt;Barcodes.&lt;/p&gt;

&lt;p&gt;Account numbers.&lt;/p&gt;

&lt;p&gt;Concepts that carry meaning within the business itself.&lt;/p&gt;

&lt;p&gt;That is their language.&lt;/p&gt;




&lt;p&gt;The information system, however, operates differently.&lt;/p&gt;

&lt;p&gt;Its relationships rely on unique, stable identities.&lt;/p&gt;

&lt;p&gt;Primary keys.&lt;/p&gt;

&lt;p&gt;GUIDs.&lt;/p&gt;

&lt;p&gt;Surrogate keys.&lt;/p&gt;

&lt;p&gt;Someone must therefore translate the language of the user into the language of the system.&lt;/p&gt;

&lt;p&gt;And that translation must be correct.&lt;/p&gt;

&lt;p&gt;Within the appropriate business context.&lt;/p&gt;




&lt;p&gt;Up to this point, one could argue that we are simply describing a search.&lt;/p&gt;

&lt;p&gt;I would probably agree.&lt;/p&gt;

&lt;p&gt;At least until the first real business scenario appears.&lt;/p&gt;

&lt;p&gt;Because a search merely returns results.&lt;/p&gt;

&lt;p&gt;Here, however, we are not simply searching.&lt;/p&gt;

&lt;p&gt;We are trying to answer a much more specific question.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which business entity does the user actually mean?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is a fundamentally different question.&lt;/p&gt;

&lt;p&gt;It is not about discovering information.&lt;/p&gt;

&lt;p&gt;It is about &lt;strong&gt;resolving a business reference&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;Let us now give names to the individual steps of this process.&lt;/p&gt;

&lt;p&gt;The user provides a business reference.&lt;/p&gt;

&lt;p&gt;The application evaluates it within the current business context.&lt;/p&gt;

&lt;p&gt;It attempts to resolve it.&lt;/p&gt;

&lt;p&gt;It arrives at a canonical business identity.&lt;/p&gt;

&lt;p&gt;Finally, it returns the information required for the task to continue.&lt;/p&gt;

&lt;p&gt;Conceptually, the process looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Business Reference
        │
        ▼
 Business Context
        │
        ▼
    Resolution
        │
        ▼
Canonical Identity
        │
        ▼
   Projection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice something interesting.&lt;/p&gt;

&lt;p&gt;There is no ComboBox.&lt;/p&gt;

&lt;p&gt;No Grid.&lt;/p&gt;

&lt;p&gt;No Dialog.&lt;/p&gt;

&lt;p&gt;In fact, there is no user interface at all.&lt;/p&gt;

&lt;p&gt;There is only a process.&lt;/p&gt;




&lt;p&gt;That process does not always produce the same outcome.&lt;/p&gt;

&lt;p&gt;It may find no matching entity.&lt;/p&gt;

&lt;p&gt;It may find exactly one.&lt;/p&gt;

&lt;p&gt;It may find a small number of possible candidates.&lt;/p&gt;

&lt;p&gt;Or it may find so many that the result is no longer useful.&lt;/p&gt;

&lt;p&gt;The last case deserves special attention.&lt;/p&gt;

&lt;p&gt;If the system returns five products, we are dealing with normal business ambiguity.&lt;/p&gt;

&lt;p&gt;The user can easily choose the correct one.&lt;/p&gt;

&lt;p&gt;If, however, it returns five thousand products, we are no longer dealing with ambiguity.&lt;/p&gt;

&lt;p&gt;We are dealing with a business reference that is simply too broad to be resolved.&lt;/p&gt;

&lt;p&gt;The problem is not the list.&lt;/p&gt;

&lt;p&gt;The problem is the reference itself.&lt;/p&gt;

&lt;p&gt;The application should not ask the user to choose one product out of five thousand.&lt;/p&gt;

&lt;p&gt;It should ask for a better business reference.&lt;/p&gt;

&lt;p&gt;This distinction is fundamental.&lt;/p&gt;

&lt;p&gt;Business ambiguity and resolution failure are not the same thing.&lt;/p&gt;




&lt;p&gt;The more closely we examine this process, the harder it becomes to view it as just another UI control.&lt;/p&gt;

&lt;p&gt;The same process can be used by a desktop application.&lt;/p&gt;

&lt;p&gt;A web application.&lt;/p&gt;

&lt;p&gt;A service.&lt;/p&gt;

&lt;p&gt;A data import process.&lt;/p&gt;

&lt;p&gt;An automated workflow.&lt;/p&gt;

&lt;p&gt;The interaction changes.&lt;/p&gt;

&lt;p&gt;The resolution process does not.&lt;/p&gt;

&lt;p&gt;And when the same concept appears in exactly the same form regardless of the application type or user interface, it stops looking like a UI detail and starts looking like an architectural concept.&lt;/p&gt;

&lt;p&gt;Perhaps this is the real meaning of the word &lt;strong&gt;Locator&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Not as a control.&lt;/p&gt;

&lt;p&gt;Not as a search mechanism.&lt;/p&gt;

&lt;p&gt;But as the name of an architectural concept.&lt;/p&gt;

&lt;p&gt;A concept with one—and only one—purpose:&lt;/p&gt;

&lt;p&gt;To transform human business references into canonical business identities within a specific business context.&lt;/p&gt;

&lt;p&gt;This is what, in this article, we call &lt;strong&gt;The Locator Pattern&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;If the Locator is indeed an architectural pattern, another question immediately follows.&lt;/p&gt;

&lt;p&gt;How should it be described?&lt;/p&gt;

&lt;p&gt;What is the minimum information required to define a Locator?&lt;/p&gt;

&lt;p&gt;How can that description remain independent of the mechanism that executes it?&lt;/p&gt;

&lt;p&gt;In other words,&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can a Locator be defined declaratively?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is precisely what we will examine in the next article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fundamental Concepts of Business Applications III: Locator Definitions&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Closing Question
&lt;/h3&gt;

&lt;p&gt;Does this concept already exist, perhaps under a different name, in the framework or platform you use?&lt;/p&gt;

&lt;p&gt;If so, I would genuinely like to learn about it.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>softwareengineering</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Fundamental Concepts of Business Applications I: Why a ComboBox Is Not Enough</title>
      <dc:creator>Theodoros Bebekis</dc:creator>
      <pubDate>Fri, 03 Jul 2026 11:53:16 +0000</pubDate>
      <link>https://dev.to/tbebekis/-fundamental-concepts-of-business-applications-i-why-a-combobox-is-not-enough-pb4</link>
      <guid>https://dev.to/tbebekis/-fundamental-concepts-of-business-applications-i-why-a-combobox-is-not-enough-pb4</guid>
      <description>&lt;h2&gt;
  
  
  Introducing the Locator
&lt;/h2&gt;

&lt;p&gt;If you have developed even a single business application, chances are you have solved the same problem many times.&lt;/p&gt;

&lt;p&gt;You have built a customer search dialog.&lt;/p&gt;

&lt;p&gt;You have implemented product autocomplete.&lt;/p&gt;

&lt;p&gt;You have written a custom editor for a data grid.&lt;/p&gt;

&lt;p&gt;You have created a selection popup.&lt;/p&gt;

&lt;p&gt;Every time, you were essentially solving the same problem.&lt;/p&gt;

&lt;p&gt;Yet most UI libraries do not treat this requirement as a distinct concept. It usually appears as a lookup, an autocomplete, a popup dialog, or some other widget. The implementation changes, but the underlying problem remains exactly the same.&lt;/p&gt;

&lt;p&gt;In this article, I would like to suggest that this recurring requirement deserves to be recognized as a fundamental concept of business applications. I will call it a &lt;strong&gt;Locator&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Problem Found in Every Business Application
&lt;/h2&gt;

&lt;p&gt;Almost every business application contains fields that reference other business entities.&lt;/p&gt;

&lt;p&gt;A sales order references a customer.&lt;/p&gt;

&lt;p&gt;An invoice references a supplier.&lt;/p&gt;

&lt;p&gt;A warehouse transaction references a product.&lt;/p&gt;

&lt;p&gt;A journal entry references an account.&lt;/p&gt;

&lt;p&gt;In the database, these relationships are stored as stable identifiers. Users, however, never think in terms of &lt;code&gt;CustomerId&lt;/code&gt; or &lt;code&gt;ProductId&lt;/code&gt;. They think in terms of customer codes, names, tax numbers, barcodes, and other business identifiers that are meaningful to them.&lt;/p&gt;

&lt;p&gt;The real problem is therefore not how to store an identifier.&lt;/p&gt;

&lt;p&gt;The real problem is how users can locate the correct business entity using the information they already know.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a ComboBox Is Not Enough
&lt;/h2&gt;

&lt;p&gt;When the dataset is small, a ComboBox is an excellent solution.&lt;/p&gt;

&lt;p&gt;Countries.&lt;/p&gt;

&lt;p&gt;Currencies.&lt;/p&gt;

&lt;p&gt;Units of Measure.&lt;/p&gt;

&lt;p&gt;Payment Methods.&lt;/p&gt;

&lt;p&gt;These are reference tables containing a few dozen or perhaps a few hundred rows. Loading them into memory is perfectly reasonable, and selecting an item from a list is both fast and convenient.&lt;/p&gt;

&lt;p&gt;The picture changes completely when we talk about Customers, Products, Suppliers, or General Ledger Accounts. Here the number of records may reach thousands—or even hundreds of thousands.&lt;/p&gt;

&lt;p&gt;At this point, the problem is no longer selecting an item from a list.&lt;/p&gt;

&lt;p&gt;The problem is &lt;strong&gt;locating&lt;/strong&gt; the correct record.&lt;/p&gt;

&lt;p&gt;And that is an entirely different problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Locator
&lt;/h2&gt;

&lt;p&gt;Most UI libraries provide general-purpose controls such as TextBox, ComboBox, ListBox, DataGrid, and TreeView.&lt;/p&gt;

&lt;p&gt;Business applications, however, need something different.&lt;/p&gt;

&lt;p&gt;They need a mechanism that allows users to locate a business entity using the information they naturally recognize, rather than its technical identifier.&lt;/p&gt;

&lt;p&gt;This mechanism is what I call a &lt;strong&gt;Locator&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Its purpose is not to display a list.&lt;/p&gt;

&lt;p&gt;Its purpose is not to suggest possible values.&lt;/p&gt;

&lt;p&gt;Its purpose is to &lt;strong&gt;resolve a business reference&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl53v1asuj92snsewx7zx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl53v1asuj92snsewx7zx.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Locator Does Not Simply Return a Value
&lt;/h2&gt;

&lt;p&gt;At first glance, a Locator may look like an advanced lookup control or an autocomplete widget.&lt;/p&gt;

&lt;p&gt;In reality, it does something far more important.&lt;/p&gt;

&lt;p&gt;It does not simply return a value.&lt;/p&gt;

&lt;p&gt;It resolves a business reference.&lt;/p&gt;

&lt;p&gt;Consider a sales order line containing a &lt;code&gt;ProductId&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;The user searches for a product by typing its code or description.&lt;/p&gt;

&lt;p&gt;Once the correct product has been selected, the application usually needs much more than the &lt;code&gt;ProductId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It may need the unit price.&lt;/p&gt;

&lt;p&gt;The unit of measure.&lt;/p&gt;

&lt;p&gt;The VAT rate.&lt;/p&gt;

&lt;p&gt;The discount category.&lt;/p&gt;

&lt;p&gt;It may even need different information depending on the customer, the company, the warehouse, or any other business context in which the search takes place.&lt;/p&gt;

&lt;p&gt;A Locator therefore does not simply return a value.&lt;/p&gt;

&lt;p&gt;It returns the result of resolving a business reference within a specific business context.&lt;/p&gt;

&lt;p&gt;That is why it is much more than an advanced lookup control.&lt;/p&gt;

&lt;h2&gt;
  
  
  It Is Not a Control. It Is a Behavior.
&lt;/h2&gt;

&lt;p&gt;This is perhaps the most important idea.&lt;/p&gt;

&lt;p&gt;A Locator is not a particular user interface control.&lt;/p&gt;

&lt;p&gt;It is a behavior.&lt;/p&gt;

&lt;p&gt;In a desktop form, it may appear as two searchable fields.&lt;/p&gt;

&lt;p&gt;In a data grid, it may be implemented as a custom cell editor.&lt;/p&gt;

&lt;p&gt;In a web application, it may appear as an autocomplete field with a popup results list.&lt;/p&gt;

&lt;p&gt;In a mobile application, it may open a dedicated search screen.&lt;/p&gt;

&lt;p&gt;The appearance changes.&lt;/p&gt;

&lt;p&gt;The behavior remains exactly the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User input

Code
Name
VAT
Barcode

        │
        ▼

     Locator

Searches
Disambiguates
Resolves

        │
        ▼

Target Context

Key
Display values
Business values
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The User Experience
&lt;/h2&gt;

&lt;p&gt;Experienced business application users work almost entirely with the keyboard.&lt;/p&gt;

&lt;p&gt;A good Locator should never interrupt that workflow.&lt;/p&gt;

&lt;p&gt;When a search produces a unique match, the selection should be completed immediately.&lt;/p&gt;

&lt;p&gt;Only when multiple possible matches exist should the user be asked to choose the correct business entity.&lt;/p&gt;

&lt;p&gt;A Locator is not only about searching.&lt;/p&gt;

&lt;p&gt;It is also about disambiguation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Every UI Library Should Include a Locator
&lt;/h2&gt;

&lt;p&gt;Every serious business application solves this problem every day.&lt;/p&gt;

&lt;p&gt;Yet most UI libraries do not recognize it as a fundamental abstraction.&lt;/p&gt;

&lt;p&gt;Instead, every application ends up implementing search dialogs, autocomplete controls, custom editors, and selection popups over and over again.&lt;/p&gt;

&lt;p&gt;The functionality is essentially the same.&lt;/p&gt;

&lt;p&gt;Only the implementation differs.&lt;/p&gt;

&lt;p&gt;I believe that the Locator represents a fundamental concept of business applications, one that is still treated primarily as a collection of unrelated UI widgets.&lt;/p&gt;

&lt;p&gt;Perhaps it is time to recognize it for what it really is: a fundamental abstraction for building data-entry and business applications.&lt;/p&gt;

&lt;p&gt;Because in business applications, the critical concept is not displaying a list.&lt;/p&gt;

&lt;p&gt;It is enabling users to locate the correct business reference.&lt;/p&gt;




&lt;p&gt;In the next article, I will leave philosophy behind and move on to architecture.&lt;/p&gt;

&lt;p&gt;What information should a Locator know?&lt;/p&gt;

&lt;p&gt;How should it be described?&lt;/p&gt;

&lt;p&gt;And how can the same definition be reused across forms, data grids, and different user interface technologies?&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>softwareengineering</category>
      <category>design</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Serialize and deserialize JSON using JsonSerializer</title>
      <dc:creator>Theodoros Bebekis</dc:creator>
      <pubDate>Wed, 04 Jun 2025 12:16:53 +0000</pubDate>
      <link>https://dev.to/tbebekis/serialize-and-deserialize-json-using-jsonserializer-1k4e</link>
      <guid>https://dev.to/tbebekis/serialize-and-deserialize-json-using-jsonserializer-1k4e</guid>
      <description>&lt;p&gt;This text explores the use of the &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializer" rel="noopener noreferrer"&gt;JsonSerializer&lt;/a&gt; .Net class in serializing and deserializing .Net classes to &lt;a href="https://www.json.org/json-en.html" rel="noopener noreferrer"&gt;JSON&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;.Net types related to serialization are found in the following namespaces&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json" rel="noopener noreferrer"&gt;System.Text.Json&lt;/a&gt;. Contains the &lt;code&gt;JsonSerializer&lt;/code&gt;, the &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions" rel="noopener noreferrer"&gt;JsonSerializerOptions&lt;/a&gt; and other main types.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization" rel="noopener noreferrer"&gt;System.Text.Json.Serialization&lt;/a&gt;. Contains attributes, converters and similar auxiliary classes used in customizing serialization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is of course the excellent &lt;a href="https://www.newtonsoft.com/json" rel="noopener noreferrer"&gt;Newtonsoft.Json&lt;/a&gt; library but &lt;code&gt;JsonSerializer&lt;/code&gt; is worth using it since it is the native solution provided by .Net and there is no need to install any &lt;a href="https://www.nuget.org/" rel="noopener noreferrer"&gt;NuGet&lt;/a&gt; package in order to use it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;JsonSerializer&lt;/code&gt; can be used with .Net Core 3.0 and later and with .Net Standard 2.0.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The full text and demo project can be found on &lt;a href="https://github.com/tbebekis/Tutorial-JsonSerializer" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Basics
&lt;/h2&gt;

&lt;p&gt;The following code entities are used in this text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public enum Status
{
    None,
    Pending,
    InProgress,
    AllCompleted
}

public class Part
{
    public string Code { get; set; }
    public decimal Amount { get; set; } 
    public bool IsCompleted { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;JsonSerializer&lt;/code&gt; is a &lt;em&gt;static&lt;/em&gt; class. No need to create an instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// serialization
Part P = new(); 
string JsonText =  JsonSerializer.Serialize(P);

// de-serialization
Part P2 = JsonSerializer.Deserialize&amp;lt;Part&amp;gt;(JsonText);

// or
P2 = JsonSerializer.Deserialize(JsonText, typeof(Part)) as Part;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  JsonSerializerOptions
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Serialize()&lt;/code&gt; and &lt;code&gt;Deserialize()&lt;/code&gt; methods accept a &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions" rel="noopener noreferrer"&gt;JsonSerializerOptions&lt;/a&gt; parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JsonSerializerOptions JsonOptions = new();

// serialization
Part P = new(); 
string JsonText = JsonSerializer.Serialize(P, JsonOptions);

// de-serialization
Part P2 = JsonSerializer.Deserialize&amp;lt;Part&amp;gt;(JsonText, JsonOptions);

// or
P2 = JsonSerializer.Deserialize(JsonText, typeof(Part), JsonOptions) as Part;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;JsonSerializerOptions&lt;/code&gt; controls the behavior of the &lt;code&gt;JsonSerializer&lt;/code&gt;. It provides a great number of properties in order to customize the serialization operation.&lt;/p&gt;

&lt;p&gt;Notable properties worth exploring are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.converters" rel="noopener noreferrer"&gt;Converters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.defaultignorecondition" rel="noopener noreferrer"&gt;DefaultIgnoreCondition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.dictionarykeypolicy" rel="noopener noreferrer"&gt;DictionaryKeyPolicy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.ignorereadonlyproperties" rel="noopener noreferrer"&gt;IgnoreReadOnlyProperties&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.includefields" rel="noopener noreferrer"&gt;IncludeFields&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.numberhandling" rel="noopener noreferrer"&gt;NumberHandling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.propertynamecaseinsensitive" rel="noopener noreferrer"&gt;PropertyNameCaseInsensitive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.propertynamingpolicy" rel="noopener noreferrer"&gt;PropertyNamingPolicy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.readcommenthandling" rel="noopener noreferrer"&gt;ReadCommentHandling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.referencehandler" rel="noopener noreferrer"&gt;ReferenceHandler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.typeinforesolver" rel="noopener noreferrer"&gt;TypeInfoResolver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.web" rel="noopener noreferrer"&gt;Web&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.writeindented" rel="noopener noreferrer"&gt;WriteIndented&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An example of creating a &lt;code&gt;JsonSerializerOptions&lt;/code&gt; instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JsonSerializerOptions Result = new();

Result.PropertyNamingPolicy = null;
Result.PropertyNameCaseInsensitive = true;
Result.WriteIndented = true;
Result.IgnoreReadOnlyProperties = true;
Result.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;  
Result.ReadCommentHandling = JsonCommentHandling.Skip;
Result.AllowTrailingCommas = true;
Result.NumberHandling = JsonNumberHandling.AllowReadingFromString;
Result.ReferenceHandler = ReferenceHandler.Preserve;  

return Result;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Attributes
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization" rel="noopener noreferrer"&gt;System.Text.Json.Serialization&lt;/a&gt; namespace provides a great number of attributes that can be used with properties or classes in order to control the serialization.&lt;/p&gt;

&lt;p&gt;Notable attributes worth exploring are:&lt;/p&gt;

&lt;h4&gt;
  
  
  [JsonConstructor]
&lt;/h4&gt;

&lt;p&gt;Indicates a constructor that should be used by the serializer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Part
{
    public Part() 
    {
    }
    [JsonConstructor]
    public Part(string code) 
    {
       Code = code;
    }
    public string Code { get; set; }  
    public decimal Amount { get; set; }  
    public bool IsCompleted { get; set; } 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  [JsonConverter]
&lt;/h4&gt;

&lt;p&gt;Specifies what converter type to be used in serialization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[JsonConverter(typeof(JsonStringEnumConverter))]
public Status Status { get; set; }

[JsonConverter(typeof(DateOnlyConverter))]
public DateOnly BirthDate { get; set; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;[JsonConverter(typeof(JsonStringEnumConverter))]&lt;/code&gt; can be used with &lt;em&gt;enum&lt;/em&gt; types also.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[JsonConverter(typeof(JsonStringEnumConverter))]
public enum Status
{
    None,
    Pending,
    InProgress,
    AllCompleted
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  [JsonIgnore]
&lt;/h4&gt;

&lt;p&gt;Indicates that the property should be ignored in serialization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[JsonIgnore]
public string Secret { get; set; }

[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string Message { get; set; } // ignored when null, the default

[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public int Value { get; set; } // ignored when 0, the default

[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public int Value2 { get; set; } =  123; // ignored when 123, the default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  [JsonInclude]
&lt;/h4&gt;

&lt;p&gt;Forces serialization of a public field or a public property even when it has just a private setter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[JsonInclude]
public int Age;

[JsonInclude]
public string ReadOnlyProperty { get; private set; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  [JsonNumberHandling]
&lt;/h4&gt;

&lt;p&gt;Controls how a number is serialized or deserialized by using a &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonnumberhandling" rel="noopener noreferrer"&gt;JsonNumberHandling&lt;/a&gt; setting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)]
public int Amount { get; set; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  [JsonPropertyName]
&lt;/h4&gt;

&lt;p&gt;Controls the name under which the property is serialized to or deserialized from.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[JsonPropertyName("user_name")]
public string UserName { get; set; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  [JsonPropertyOrder]
&lt;/h4&gt;

&lt;p&gt;Controls the serialization order of the property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[JsonPropertyOrder(5)]
public string Name { get; set; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  [JsonRequired]
&lt;/h4&gt;

&lt;p&gt;Dictates that the property must be present.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[JsonRequired]
public string Name { get; set; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Attributes from other namespaces
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;None of the following attributes&lt;/strong&gt; is used in &lt;code&gt;System.Text.Json&lt;/code&gt; serialization. &lt;/p&gt;

&lt;p&gt;Only the attributes found in &lt;code&gt;System.Text.Json.Serialization&lt;/code&gt; are taken into account. The &lt;code&gt;System.Text.Json&lt;/code&gt; namespace has its own attributes, all with &lt;code&gt;Json&lt;/code&gt; as prefix.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Except of the &lt;code&gt;System.Text.Json&lt;/code&gt; there are some other namespaces providing validation attributes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;System.ComponentModel.DataAnnotations&lt;/code&gt; namespace. Provides a number of attributes such as &lt;code&gt;[MaxLength]&lt;/code&gt;, &lt;code&gt;[Required]&lt;/code&gt;, &lt;code&gt;[Range]&lt;/code&gt;, etc. Used in &lt;code&gt;Binary Serialization&lt;/code&gt; or &lt;code&gt;SOAP Serialization&lt;/code&gt;. Also used in Asp.Net Core &lt;code&gt;MVC&lt;/code&gt; and &lt;code&gt;WebAPI&lt;/code&gt; model validation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;System.Runtime.Serialization&lt;/code&gt; namespace. Provides  attributes such as &lt;code&gt;[DataContract]&lt;/code&gt; and &lt;code&gt;[DataMember]&lt;/code&gt;. Used by &lt;code&gt;DataContractSerializer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;System.Xml.Serialization&lt;/code&gt; namespace. Provides attributes such as &lt;code&gt;[XmlRoot]&lt;/code&gt;, &lt;code&gt;[XmlElement]&lt;/code&gt;, &lt;code&gt;[XmlAttribute]&lt;/code&gt;. Used in &lt;code&gt;XML Serialization&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The static &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.validator" rel="noopener noreferrer"&gt;System.ComponentModel.DataAnnotations.Validator&lt;/a&gt; class can be used to manually validate classes annotated with &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.validationattribute" rel="noopener noreferrer"&gt;ValidationAttribute&lt;/a&gt; derived attributes, such as &lt;code&gt;MaxLength&lt;/code&gt; and &lt;code&gt;Range&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MyModel Model = JsonSerializer.Deserialize&amp;lt;MyModel&amp;gt;(JsonText);

List&amp;lt;string&amp;gt; ErrorList = Validate(Model);

...

public List&amp;lt;string&amp;gt; Validate(object Instance)
{
    List&amp;lt;string&amp;gt; ErrorList = new();
    var validationContext = new ValidationContext(Instance);
    var validationResults = new List&amp;lt;ValidationResult&amp;gt;();

    // not valid?
    // collect validation errors in a list
    if (!Validator.TryValidateObject(Instance, validationContext, validationResults, true))
    {
        foreach (var validationResult in validationResults)
        {
            ErrorList.Add(validationResult.ErrorMessage);
        }        
    }

    return ErrorList; // empty list means Instance is valid
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Asp.Net Core MVC or WebAPI controllers the &lt;code&gt;ModelState.IsValid&lt;/code&gt; is used to validate attributes based on &lt;code&gt;System.ComponentModel.DataAnnotations&lt;/code&gt; namespace annotations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customize serialization with Converters
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/converters-how-to" rel="noopener noreferrer"&gt;converter&lt;/a&gt; converts an object or a value to and from JSON text.  &lt;/p&gt;

&lt;p&gt;A custom converter can also be used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[JsonConverter(typeof(CustomDateOnlyConverter))]
public DateOnly BirthDate { get; set; }

...

public class CustomDateOnlyConverter : JsonConverter&amp;lt;DateOnly&amp;gt;
{
    public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return DateOnly.Parse(reader.GetString());
    }

    public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString("yyyy-MM-dd"));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two patterns in creating a custom converter&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/converters-how-to#sample-basic-converter" rel="noopener noreferrer"&gt;Basic pattern&lt;/a&gt;. The custom converter derives from &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonconverter-1" rel="noopener noreferrer"&gt;&lt;code&gt;JsonConverter&amp;lt;TValue&amp;gt;&lt;/code&gt;&lt;/a&gt; class.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/converters-how-to#sample-factory-pattern-converter" rel="noopener noreferrer"&gt;Factory pattern&lt;/a&gt;. The custom converter derives from &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonconverterfactory" rel="noopener noreferrer"&gt;JsonConverterFactory&lt;/a&gt; class.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A custom converter can be registered&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;by adding an instance of the custom converter to &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.converters" rel="noopener noreferrer"&gt;JsonSerializerOptions.Converters&lt;/a&gt; collection&lt;/li&gt;
&lt;li&gt;by applying the &lt;code&gt;[JsonConverter]&lt;/code&gt; to a class that represents a custom value type&lt;/li&gt;
&lt;li&gt;by applying the &lt;code&gt;[JsonConverter]&lt;/code&gt; to properties that require the custom converter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When there are multiple converters applied then there are &lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/converters-how-to#converter-registration-precedence" rel="noopener noreferrer"&gt;rules that dictate the order&lt;/a&gt; by which a converter is chosen in serialization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customize serialization with a Resolver and Modifier functions
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.typeinforesolver" rel="noopener noreferrer"&gt;JsonSerializerOptions.TypeInfoResolver&lt;/a&gt; property provides a way to plug &lt;code&gt;modifier&lt;/code&gt; functions of the type &lt;code&gt;Action&amp;lt;JsonTypeInfo&amp;gt;&lt;/code&gt; into serialization.&lt;/p&gt;

&lt;p&gt;Inline modifiers with lambda functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JsonSerializerOptions JsonOptions = new()
{
    TypeInfoResolver = new DefaultJsonTypeInfoResolver
    {
        Modifiers =
        {
            (TypeInfo) =&amp;gt; {
                //...
            },
            (TypeInfo) =&amp;gt; {
                //...
            }
        }
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or usual methods in a class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;static public class Helper
{
    static public void ModifierFunc1(JsonTypeInfo TypeInfo)
    {
        //...
    }
    static public void ModifierFunc2(JsonTypeInfo TypeInfo)
    {
        //...
    }
}

JsonSerializerOptions JsonOptions = new();
Json.Options.Modifiers.Add(Helper.ModifierFunc1);
Json.Options.Modifiers.Add(Helper.ModifierFunc2);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a custom resolver that excludes a list of specified properties from serialization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ExcludePropertiesTypeInfoResolver : DefaultJsonTypeInfoResolver
{
    string[] ExcludeProperties = new string[0];

    static void RemoveAll&amp;lt;T&amp;gt;(IList&amp;lt;T&amp;gt; list, Predicate&amp;lt;T&amp;gt; predicate)
    {
        for (int i = 0; i &amp;lt; list.Count; i++)
        {
            if (predicate(list[i]))
            {
                list.RemoveAt(i--);
            }
        }
    }
    void ModifierFunc(JsonTypeInfo TypeInfo)
    {
        if (TypeInfo.Kind != JsonTypeInfoKind.Object)
            return;

        RemoveAll(TypeInfo.Properties, prop =&amp;gt; ExcludeProperties.Contains(prop.Name)); 
    }

    public ExcludePropertiesTypeInfoResolver(string[] ExcludeProperties)
    {
        this.ExcludeProperties = ExcludeProperties;
        this.Modifiers.Insert(0, ModifierFunc);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is how to use it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var ExcludeProperties = new[] { "Prop1", "Prop2"};

JsonSerializerOptions JsonOptions = new()
{
    TypeInfoResolver = new ExcludePropertiesTypeInfoResolver(ExcludeProperties)
}; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization.metadata.jsontypeinfo" rel="noopener noreferrer"&gt;JsonTypeInfo&lt;/a&gt; provides metadata about the type being serialized.&lt;/p&gt;

&lt;p&gt;Regarding modifier functions .Net Core docs provide a number of &lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/custom-contracts#modifiers" rel="noopener noreferrer"&gt;examples&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Property Name Casing
&lt;/h2&gt;

&lt;p&gt;The casing of a property name, such as camel-casing, is controlled by the &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.propertynamingpolicy" rel="noopener noreferrer"&gt;JsonSerializerOptions.PropertyNamingPolicy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PropertyNamingPolicy&lt;/code&gt; property is a &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonnamingpolicy" rel="noopener noreferrer"&gt;JsonNamingPolicy&lt;/a&gt; derived class. When it is &lt;strong&gt;null&lt;/strong&gt;, the default, property names remain unchanged.&lt;/p&gt;

&lt;p&gt;That &lt;code&gt;JsonNamingPolicy&lt;/code&gt; class provides a number of static properties that return a &lt;code&gt;JsonNamingPolicy&lt;/code&gt; derived class instance, such as &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonnamingpolicy.camelcase" rel="noopener noreferrer"&gt;CamelCase&lt;/a&gt; or &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonnamingpolicy.snakecaselower" rel="noopener noreferrer"&gt;SnakeCaseLower&lt;/a&gt;. Each one for a specific casing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JsonSerializerOptions JsonOptions = new();

JsonOptions.PropertyNamingPolicy = JsonNamingPolicy.CameCase; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The PopulateObject() problem.
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;System.Text.Json&lt;/code&gt; provides a solution under the title &lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/populate-properties" rel="noopener noreferrer"&gt;Populate initialized properties&lt;/a&gt; which is far from what is actully needed.&lt;/p&gt;

&lt;p&gt;Frequently there are cases where there is an already constructed instance that needs to be populated using data coming as json text. This is a problem that the &lt;code&gt;System.Text.Json&lt;/code&gt; has no solution to offer yet.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;JsonSerializer.Deserialize()&lt;/code&gt; methods always create and return a new instance. This is not always what an application needs. &lt;/p&gt;

&lt;p&gt;But deep in the .Net source code there is a class containing a method that do just that. The &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.graph.derivedtypeconverter" rel="noopener noreferrer"&gt;Microsoft.Graph.DerivedTypeConverter&lt;/a&gt; contains a &lt;strong&gt;private&lt;/strong&gt; method, named &lt;a href="https://github.com/microsoftgraph/msgraph-sdk-dotnet-core/blob/57861dc4aea6c33908838915c97fc02105b6e788/src/Microsoft.Graph.Core/Serialization/DerivedTypeConverter.cs#L112-L114" rel="noopener noreferrer"&gt;PopulateObject()&lt;/a&gt; which does exactly what it says.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The project that accompanies this text contains a static class under the name &lt;code&gt;NetJson&lt;/code&gt; which provides, among other useful utilities, a &lt;code&gt;PopulateObject()&lt;/code&gt; method. This &lt;code&gt;PopulateObject()&lt;/code&gt; method is just the code from the &lt;code&gt;Microsoft.Graph.DerivedTypeConverter.PopulateObject()&lt;/code&gt; private method.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;static public void PopulateObject(object Instance, string JsonText, JsonSerializerOptions Options)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Document Object Model (DOM) of System.Text.Json
&lt;/h2&gt;

&lt;p&gt;Except of the &lt;code&gt;JsonSerializer&lt;/code&gt; the .Net Core serialization sub-system provides a &lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/use-dom" rel="noopener noreferrer"&gt;DOM model&lt;/a&gt; too.&lt;/p&gt;

&lt;p&gt;The system provides two ways in building a DOM model.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.nodes.jsonobject" rel="noopener noreferrer"&gt;System.Text.Json.JsonObject&lt;/a&gt; class, along with &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.nodes.jsonnode" rel="noopener noreferrer"&gt;JsonNode&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.nodes.jsonarray" rel="noopener noreferrer"&gt;JsonArray&lt;/a&gt; and &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.nodes.jsonvalue" rel="noopener noreferrer"&gt;JsonValue&lt;/a&gt; classes&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsondocument" rel="noopener noreferrer"&gt;System.Text.Json.JsonDocument&lt;/a&gt; along with &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonelement" rel="noopener noreferrer"&gt;JsonElement&lt;/a&gt; class.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  JsonObject, JsonNode, JsonArray and JsonValue
&lt;/h2&gt;

&lt;p&gt;These are mutable classes, meaning the application may add, modify or remove elements in the DOM tree.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;JsonNode&lt;/code&gt; is an abstract class. Besides that it provides a great number of &lt;strong&gt;static&lt;/strong&gt; helper methods for adding elements to the DOM tree. It also serves as the base class for the others in this group.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;JsonObject&lt;/code&gt; represents a mutable DOM object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;JsonArray&lt;/code&gt; represents a mutable DOM array object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;JsonValue&lt;/code&gt; represents a mutable DOM value object.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the above provide the following properties &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an integer indexer property &lt;code&gt;Item[Int32]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;a string indexer property &lt;code&gt;Item[String]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;Count&lt;/code&gt; property&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the above provide the following methods &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AsObject()&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AsArray()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AsValue()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetPath()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetPropertyName()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetType()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GetValue&amp;lt;T&amp;gt;()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GetValueKind()&lt;/code&gt; which returns a value of the &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonvaluekind" rel="noopener noreferrer"&gt;JsonValueKind&lt;/a&gt; enum&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ReplaceWith&amp;lt;T&amp;gt;(T)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ToJsonString()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;JsonObject&lt;/code&gt; and &lt;code&gt;JsonArray&lt;/code&gt; provide the following methods too&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Add()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Clear()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Remove()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RemoveAt()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Primitive Values using JsonValue.Create(AnyPrimitiveValue)
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;JsonObject&lt;/code&gt; properties are &lt;code&gt;Key-Value&lt;/code&gt; pairs, i.e. &lt;code&gt;JORoot.Add(PropertyName, PropertyValue)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;JsonValue.Create(AnyPrimitiveValue)&lt;/code&gt; is used with primitive Types such as string and integer, in creating new &lt;code&gt;JsonValue&lt;/code&gt; objects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JsonObject JORoot = new();
JORoot.Add("String", JsonValue.Create("This is a JsonValue"));
JORoot.Add("DateTime", JsonValue.Create(DateTime.Now));
JORoot.Add("Integer", JsonValue.Create(123));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Removing a Property
&lt;/h4&gt;

&lt;p&gt;Using the &lt;code&gt;Remove(PropertyName)&lt;/code&gt; removes the property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JORoot.Remove("DateTime");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  JsonObject is a Dictionary-like object
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;JsonObject&lt;/code&gt; instances are &lt;code&gt;Dictionary-like&lt;/code&gt; objects and a new &lt;code&gt;JsonObject&lt;/code&gt; can be initialized as following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JsonObject JORoot = new JsonObject
{
    ["Key1"] = "This is a string",
    ["Key2"] = DateTime.Now,
    ["Key3"] = false,
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  The JsonNode.Parse() method
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;JsonNode.Parse(JsonText)&lt;/code&gt; &lt;strong&gt;static&lt;/strong&gt; method parses text and returns a &lt;code&gt;JsonNode&lt;/code&gt; object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JsonObject JORoot = new();
JORoot.Add("Person", JsonNode.Parse("""{ "Name": "John Doe", "Age": 30 }"""));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Using the JsonValue.Create&amp;lt;T&amp;gt;() with non-primitive Types
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;JsonValue.Create&amp;lt;T&amp;gt;()&lt;/code&gt; is used with non-primitive Types such as user defined classes, in creating new &lt;code&gt;JsonValue&lt;/code&gt; objects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JsonObject JORoot = new();
JORoot.Add("Part", JsonValue.Create&amp;lt;Part&amp;gt;(new Part()));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Initializing a JsonArray
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JsonObject JORoot = new();
JsonArray JOArray = new JsonArray() { 123, true, DateTime.Now, "string value" };
JORoot.Add("Array", JOArray);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Using a Dictionary
&lt;/h4&gt;

&lt;p&gt;A &lt;code&gt;Dictionary&amp;lt;string, JsonNode&amp;gt;&lt;/code&gt; can be used in adding a property to a &lt;code&gt;JsonObject&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Dictionary&amp;lt;string, JsonNode&amp;gt;&lt;/code&gt; dictionary has to be converted to a &lt;code&gt;JsonObject&lt;/code&gt; first.&lt;/p&gt;

&lt;p&gt;This can be done because &lt;code&gt;JsonObject&lt;/code&gt; provides a suitable constructor.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;public JsonObject(IEnumerable&amp;lt;KeyValuePair&amp;lt;string, JsonNode?&amp;gt;&amp;gt; properties, JsonNodeOptions? options = null)&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JsonObject JORoot = new();

var Dictionary = new Dictionary&amp;lt;string, JsonNode&amp;gt;
{
    ["Key1"] = "This is a string",
    ["Key2"] = DateTime.Now,
    ["Key3"] = false,
    ["Key4"] = JsonValue.Create&amp;lt;Status&amp;gt;(Status.InProgress),
};

JsonObject DicNode = new JsonObject(Dictionary);
JORoot.Add("Dictionary", DicNode);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Accessing Properties and Values
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;string DemoJsonText = """
        {
            "Id": 1,
            "Name": "Model 1",
            "Status": "InProgress",
            "Active": true,
            "Parts": [
                {
                "Code": "001",
                "Amount": 1.2,
                "IsCompleted": true
                },
                {
                "Code": "002",
                "Amount": 3.4,
                "IsCompleted": false
                }
            ],
            "Properties": {
            "John": "Doe",
            "NiceCar": "Volvo"
            },
            "DT": "2025-06-04T00:59:25.6948527+03:00"
        }
        """;

JsonNode RootNode = JsonNode.Parse(DemoJsonText);

// accessing array
JsonNode PartsNode = RootNode["Parts"];
JsonNode FirstPartNode = PartsNode[0]; 

// adding new property
JsonObject ThirdPartNode = new();
ThirdPartNode["Code"] = "003";
ThirdPartNode["Amount"] = 12.3;
ThirdPartNode["IsCompleted"] = true;

// get node as array
JsonArray ArrayNode = PartsNode.AsArray();
ArrayNode.Add(ThirdPartNode);

// typecasting nodes
JsonNode PropNode = ThirdPartNode["Amount"];
double V = (double)PropNode;
// 12.3

string S = (string)ThirdPartNode["Code"];
// 003

// using the GetValue&amp;lt;T&amp;gt;()
DateTime DateTimeNode = RootNode["DT"].GetValue&amp;lt;DateTime&amp;gt;();

// get the path
string S2 = RootNode["Parts"][0].GetPath();
// $.Parts[0]   where $ denotes the root node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  JsonDocument
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;JsonDocument&lt;/code&gt; is used in building a &lt;strong&gt;read-only&lt;/strong&gt; DOM. It provides the &lt;code&gt;RootElement&lt;/code&gt; of type &lt;code&gt;JsonElement&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;JsonDocument&lt;/code&gt; elements are accessed using the &lt;code&gt;JsonElement&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;JsonElement&lt;/code&gt; class provides enumerators in order to iterate over its elements.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;JsonElement&lt;/code&gt; class provides methods such as &lt;code&gt;GetInt32()&lt;/code&gt; and &lt;code&gt;TryGetInt32()&lt;/code&gt; which convert JSON text to .Net primitive types.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: &lt;code&gt;JsonElement&lt;/code&gt; is an &lt;code&gt;IDisposable&lt;/code&gt; type.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;double Total = 0;

using (JsonDocument Doc = JsonDocument.Parse(DemoJsonText))
{
    JsonElement Root = Doc.RootElement;
    JsonElement PartsProperty = Root.GetProperty("Parts");
    foreach (JsonElement PartProperty in PartsProperty.EnumerateArray())
    {
        if (PartProperty.TryGetProperty("Amount", out JsonElement AmountElement))
        {
            Total += AmountElement.GetDouble();
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
  </channel>
</rss>
