The Error
JSON response shows: {"FirstName":"John"} but client expects {"firstName":"john"}
// Or: System.Text.Json.JsonException: The JSON value could not be converted
Quick Fix - 1 Minute
// Program.cs - Dev Fix: Configure JSON options.NET 8
builder.Services.Configure(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; // Dev Fix
options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; // Dev Fix: Accept PascalCase
options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
});
// For specific property
public class User {
[JsonPropertyName("user_id")] // Dev Fix: Force name
public int Id { get; set; }
[JsonIgnore] // Hide from JSON
public string Password { get; set; }
}
Why This Happens
System.Text.Json defaults to PascalCase. JavaScript expects camelCase. Deserialization fails if names don't match..NET 8 is case-sensitive unless configured.
Real-World Scenario: Controllers Work, Minimal APIs Don't
#1.NET 8 gotcha. You set JSON options but Minimal API ignores them:
// WRONG: This only affects Controllers, not Minimal APIs
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
// Minimal API still returns PascalCase
app.MapGet("/user", () => new { FirstName = "John" }); // Returns {"FirstName":"John"}
// RIGHT: Configure HTTP JSON options for Minimal API
builder.Services.ConfigureHttpJsonOptions(options =>
{
options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
options.SerializerOptions.PropertyNameCaseInsensitive = true;
options.SerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
});
// Now Minimal API returns camelCase
app.MapGet("/user", () => new { FirstName = "John" }); // Returns {"firstName":"John"}
Why this happens: Controllers use AddControllers().AddJsonOptions(). Minimal APIs use ConfigureHttpJsonOptions(). Different DI keys. You need both if you mix them.
Related Fixes You Should Know
JSON naming issues cascade into these:
- Minimal API 400 Bad Request - JSON sends
{"firstName":"John"}but C# expectsFirstName. Case mismatch = 400 or model is null. SetPropertyNameCaseInsensitive = true. - JSON Deserialization Error - External API sends snake_case
user_idbut your C# hasUserId. Use[JsonPropertyName("user_id")]orJsonNamingPolicy.SnakeCaseLower. - System.Text.Json Required Property - CamelCase config works but missing required field still throws..NET 8
requiredkeyword enforces at deserialization. - Model Binding Null.NET 8 - JSON looks right but DTO is null. Property names don't match due to casing. Check
PropertyNamingPolicy+[FromBody].
FAQ
Q: Why is System.Text.Json case-sensitive by default?
Performance. Case-insensitive matching is slower. JSON spec is case-sensitive. Browsers always send exact casing. Set PropertyNameCaseInsensitive = true only if you control both client and server.
Q: How do I serialize enums as strings instead of numbers?
Add converter globally: options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());. Now enum Status { Active } serializes to "Active" not 0.
Best Practice for.NET 8
- Global: Set
PropertyNamingPolicy = CamelCaseonce - Case insensitive:
PropertyNameCaseInsensitive = trueaccepts both - For APIs: use
[JsonPropertyName]to match external contracts - Enums: Add
JsonStringEnumConverterto serialize as strings
No comments yet. Be the first to share your thoughts!