DEV Community

alex_zhao_189
alex_zhao_189

Posted on

JSON Serialization and Deserialization with System.Text.Json

Everyone knows how to use JSON serialization and deserialization with System.Text.Json, but most people use it somewhat vaguely.
This article aims to help you understand and master System.Text.Json clearly, because...

"Clarity" is the sign that knowledge has truly been learned and internalized. 😊


Why System.Text.Json? 😊

There are many excellent open-source JSON libraries in .NET, such as Newtonsoft.Json.
So, why should we use System.Text.Json?

Because:

  • It's officially provided by Microsoft and built into .NET Core 3.0+; all modern Microsoft code uses System.Text.Json, so understanding it is important!
  • High performance and low memory allocation, as stated in official documentation.
  • Thread-safe by design.

Terminology:

  • Serialization: Converting an object into a string (i.e., Object β†’ string)
  • Deserialization: Converting a string into an object (i.e., string β†’ Object)

Namespaces Involved πŸš€πŸš€

  • System.Text.Json: The core namespace that provides classes like JsonSerializer for serialization/deserialization.
  • System.Text.Json.Serialization: Provides attributes such as [JsonPropertyName], and extensions for JsonSerializerOptions.
  • System.Net.Http.Json: Used with HttpClient to deserialize responses conveniently when making HTTP calls.

Basic Usage (Serialization / Deserialization) πŸŽ‰πŸŽ‰

βœ… Serialization

Use JsonSerializer.Serialize() or its generic overload JsonSerializer.Serialize<T>(). Async versions are also available.

using demo;
using System.Text.Json;
using System.Text.Json.Serialization;

var person = new Person("John Doe", 30, true, new DateTime(1993, 5, 15));

var jsonString = JsonSerializer.Serialize(person);
var jsonString2 = JsonSerializer.Serialize<Person>(person);

Console.WriteLine(jsonString);
Console.WriteLine(jsonString2);

// Output: {"Name":"John Doe","Age":30,"IsStudent":true,"Birthday":"1993-05-15T00:00:00"}
Enter fullscreen mode Exit fullscreen mode

⚠️ Note:
By default, the JSON output is minified (no indentation, newlines, or extra whitespace),
which can be hard to read in logs.
You can configure this with JsonSerializerOptions, which we'll cover below.


βœ… Deserialization

Use JsonSerializer.Deserialize() or JsonSerializer.Deserialize<T>(). Async versions are also available.

using demo;
using System.Text.Json;
using System.Text.Json.Serialization;

var jsonString = """
    {"Date":"2025-06-23T01:11:58.4217508+08:00","TemperatureCelsius":25,"Summary":"Sunny","Wind":10}
""";
var jsonObject = JsonSerializer.Deserialize<WeatherForecast>(jsonString);

Console.WriteLine(jsonObject?.Date);
Console.WriteLine(jsonObject?.TemperatureCelsius);
Console.WriteLine(jsonObject?.Summary);
Console.WriteLine(jsonObject?.WindSpeed);
Enter fullscreen mode Exit fullscreen mode

Controlling Serialization / Deserialization Behavior πŸš€πŸš€

What does it mean to "control behavior"? πŸ˜‚

For example:
When building frontend-backend applications, frontend field names are usually camelCase,
while C# uses PascalCase. So we often need to convert property names β€”
this requires customization of serialization behavior.

Another example:
By default, System.Text.Json only serializes/deserializes public properties β€”
not fields. If you want to include fields, you need to configure that explicitly.


There are two main ways to control serialization behavior:

  1. Using attributes like [JsonPropertyName], [JsonIgnore], [JsonInclude]
  2. Using the JsonSerializerOptions class

Note 1: Both attributes and JsonSerializerOptions can influence behavior.
Attributes are better for per-property control, while JsonSerializerOptions is ideal for global or complex configuration.

Note 2: Attributes take precedence over settings in JsonSerializerOptions.


πŸ”§ JsonSerializerOptions

πŸ”Έ Custom Property Naming

using demo;
using System.Text.Json;
using System.Text.Json.Serialization;

var weather = new WeatherForecast()
{
    Date = DateTimeOffset.Now,
    TemperatureCelsius = 25,
    Summary = "Sunny",
    WindSpeed = 10
};

var jsonoptions = new JsonSerializerOptions
{
   PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};

var json = JsonSerializer.Serialize(weather, jsonoptions);
Console.WriteLine(json);
Enter fullscreen mode Exit fullscreen mode

πŸ“€ Output:

{"date":"2025-06-23T02:04:44.6282091+08:00","temperatureCelsius":25,"summary":"Sunny","Wind":10}
Enter fullscreen mode Exit fullscreen mode

βœ… All property names are now in camelCase, as typically expected in web APIs.


πŸ”Έ Built-in Naming Policies

Naming Policy Description Original Converted
CamelCase First word lowercase, subsequent words capitalized TempCelsius tempCelsius
KebabCaseLower Lowercase words separated by hyphens TempCelsius temp-celsius
KebabCaseUpper Uppercase words separated by hyphens TempCelsius TEMP-CELSIUS
SnakeCaseLower Lowercase words separated by underscores TempCelsius temp_celsius
SnakeCaseUpper Uppercase words separated by underscores TempCelsius TEMP_CELSIUS

πŸ”Έ Pretty Print / Human-Friendly Output

var jsonoptions = new JsonSerializerOptions
{
    WriteIndented = true
};

var json = JsonSerializer.Serialize(weather, jsonoptions);
Console.WriteLine(json);
Enter fullscreen mode Exit fullscreen mode

🧾 Output:

{
  "Date": "2025-06-23T02:10:26.5399846+08:00",
  "TemperatureCelsius": 25,
  "Summary": "Sunny",
  "Wind": 10
}
Enter fullscreen mode Exit fullscreen mode

Much easier to read in logs or console compared to minified one-liner JSON.


πŸ”Έ Ignoring Properties (Exclude from Serialization)

public class WeatherForecastWithIgnoreAttribute
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }

    [JsonIgnore]
    public string? Summary { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

πŸ“€ Output:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25
  // "Summary" is missing
}
Enter fullscreen mode Exit fullscreen mode

πŸ”Έ Including Fields (Fields are not serialized by default)

// 1. Use attribute-based inclusion
public class Forecast2
{
    [JsonInclude]
    public DateTime Date;

    [JsonInclude]
    public int TemperatureC;

    [JsonInclude]
    public string? Summary;
}

// 2. Or globally allow fields via JsonSerializerOptions.IncludeFields
Enter fullscreen mode Exit fullscreen mode

πŸ“š Further Learning πŸŽ‰πŸŽ‰

For more details, refer to the official Microsoft documentation:
πŸ‘‰ .NET JSON serialization and deserialization

Top comments (0)