JSON conventions

edit

The service defaults configure the JSON serializer of minimal APIs (Microsoft.AspNetCore.Http.Json.JsonOptions) and of controllers (Microsoft.AspNetCore.Mvc.JsonOptions) the same way. For this endpoint:

app.MapGet("/schedule", () => new
{
    Day = DayOfWeek.Monday,
    Comment = (string?)null,
    SlotsPerRoom = new Dictionary<string, int>(StringComparer.Ordinal) { ["MeetingRoom"] = 3 },
});

the response is:

var json = await httpClient.GetStringAsync("/schedule");
Assert.Equal("""{"day":"monday","slotsPerRoom":{"meetingRoom":3}}""", json);

The conventions

SettingValueEffect
PropertyNamingPolicycamelCaseSlotsPerRoom is written slotsPerRoom
DictionaryKeyPolicycamelCaseThe MeetingRoom key is written meetingRoom
DefaultIgnoreConditionWhenWritingNullnull properties are not written
Enum converterJsonStringEnumConverter with camelCase, integers allowedEnums are written as camelCase strings; numbers are still accepted when reading
RespectNullableAnnotationstrueReading null into a non-nullable property, or writing null from one, fails
RespectRequiredConstructorParameterstrueReading an object without a value for a non-optional constructor parameter fails

The last two settings make the serializer enforce the nullable annotations and constructors of your types: a request body with a missing or null value where your type does not allow it is rejected instead of producing an object in an invalid state.

Changing the conventions

ConfigureJsonOptions runs after the conventions, so it can add converters or override any setting:

builder.UseMeziantouConventions(options =>
{
    options.OpenApi.RoutePattern = "/swagger/{documentName}.json";
    options.Https.HstsEnabled = false;
    options.AntiForgery.Enabled = false;
    options.ForwardedHeaders.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    options.ConfigureJsonOptions = json => json.WriteIndented = true;
    options.OpenTelemetry.ConfigureTracing = tracing => tracing.AddSource("MyCompany.*");
});

Dictionary keys are camelCased too: a dictionary whose keys are identifiers, such as product codes, is written with its first letter lowercased. Set DictionaryKeyPolicy to null in ConfigureJsonOptions to keep the keys unchanged.