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 likeJsonSerializer
for serialization/deserialization.System.Text.Json.Serialization
: Provides attributes such as[JsonPropertyName]
, and extensions forJsonSerializerOptions
.System.Net
.Http.Json
: Used withHttpClient
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"}
โ ๏ธ 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);
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:
Using attributes like
[JsonPropertyName]
,[JsonIgnore]
,[JsonInclude]
Using the
JsonSerializerOptions
class
Note 1: Both attributes and
JsonSerializerOptions
can influence behavior. Attributes are better for per-property control, whileJsonSerializerOptions
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);
๐ค Output:
{"date":"2025-06-23T02:04:44.6282091+08:00","temperatureCelsius":25,"summary":"Sunny","Wind":10}
โ 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);
๐งพ Output:
{
"Date": "2025-06-23T02:10:26.5399846+08:00",
"TemperatureCelsius": 25,
"Summary": "Sunny",
"Wind": 10
}
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; }
}
๐ค Output:
{
"Date": "2019-08-01T00:00:00-07:00",
"TemperatureCelsius": 25
// "Summary" is missing
}
๐ธ 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
๐ Further Learning ๐๐
For more details, refer to the official Microsoft documentation: ๐ .NET JSON serialization and deserialization
Subscribe to my newsletter
Read articles from alex zhao directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

alex zhao
alex zhao
full-stack developer,Cat Lovers