Configuring Strict JSON Behaviour In C# & .NET
[C#, .NET]
One of the things people quickly discover about the System.Text.Json serializer is that it is fairly conservative in its default configuration.
This means that by default, it will process JSON as follows:
- Case-sensitive attributes -
Nameis not the same asname - Comments are disallowed
- Trailing commas are disallowed
- Number handling is strict -
"7"will not be accepted, but7will - Properties with
nullvalues are written
Let us demonstrate this using the following type:
public sealed class Spy
{
public string FirstName { get; set; }
public string Surname { get; set; }
public string? MiddleName { get; set; }
public DateOnly DateOfBirth { get; set; }
}
This behavior outlined is what you get when you run the following code:
var james = new Spy
{
FirstName = "James",
Surname = "Bond",
MiddleName = null,
DateOfBirth = new DateOnly(1970, 1, 1)
};
var json = JsonSerializer.Serialize(james, JsonSerializerOptions.Default);
Console.WriteLine(json);
Here we are setting the options using the singleton JsonSerializerOptions.Default
This will print the following:
{
"FirstName": "James",
"Surname": "Bond",
"MiddleName": null,
"DateOfBirth": "1970-01-01"
}
If used in a context like ASP.NET, the defaults are a bit different:
- Case-insensitive attributes -
namewill be parsed and set for a type with the propertyName - Number handling allows reading from strings, so both
7and"7"will be accepted”
This is because we must be a bit more permissive when consuming JSON generated from other systems.
The code looks like this:
var jason = new Spy
{
FirstName = "Jason",
Surname = "Bourne",
MiddleName = null,
DateOfBirth = new DateOnly(1970, 1, 1)
};
json = JsonSerializer.Serialize(jason, JsonSerializerOptions.Default);
Console.WriteLine(json);
Here we are using the settings defined in the singleton JsonSerializerOptions.Web
This produces the following:
{
"FirstName": "Jason",
"Surname": "Bourne",
"MiddleName": null,
"DateOfBirth": "1970-01-01"
}
Note the difference in casing.
This is a feature, and not a bug, being a departure from Newtonsoft.Json that generally transparently figured out what to do.
Always be explicit to prevent surprises downstream.
You can further go ahead to define even more conservative settings, like so:
var options = new JsonSerializerOptions
{
AllowDuplicateProperties = false,
PropertyNameCaseInsensitive = false,
RespectNullableAnnotations = true,
RespectRequiredConstructorParameters = true,
UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow,
};
Your code for reading JSON would look like this:
var spy = JsonSerializer.Deserialize<Spy>(json, options);
You can further eliminate having to keep defining these settings yourself and use the singleton introduced in .NET 10, JsonSerializerOptions.Strict
At the time of writing this, the documentation is wanting as it does not, in fact, define what Strict is, and you have to read the code yourself to get it. This, I suspect, is because the documentation is generated.

TLDR
You can configure even stricter JSON handling using the singleton JsonSerializerOptions.Strict
Happy hacking!