Configuration

Complete reference for all JSON Serialization configuration options.


JsonSerializationOptions

Namespace: AspNetConventions.Configuration.Options
Accessed via: options.Json

Controls JSON serialization behaviour application-wide, covering both API response output and model serialization. The default underlying serializer is System.Text.Json.

Property Type Default Description
IsEnabled bool true Enables or disables AspNetConventions JSON configuration. When false, the application’s default serializer settings are used unchanged
CaseStyle CasingStyle CamelCase JSON property naming style applied globally
CaseConverter ICaseConverter? null Custom case converter for property names. Takes precedence over CaseStyle when set
ConfigureTypes Action<IJsonTypesConfigurationBuilder>? null Delegate for registering per-type and global JSON serialization rules
WriteIndented bool false When true, JSON output is pretty-printed with indentation
CaseInsensitive bool false When true, property name matching during deserialization is case-insensitive
AllowTrailingCommas bool false When true, trailing commas in JSON input are tolerated during deserialization
MaxDepth int 0 Maximum depth of nested JSON objects. 0 uses the serializer’s default (64 for System.Text.Json)
UseStringEnumConverter bool true When true, enum values are serialized as strings using the active naming policy. When false, enums are serialized as integers
NumberHandling NumberHandling Strict Controls how numbers are read and written
IgnoreCondition IgnoreCondition Never Global default ignore condition applied to all properties
Converters IReadOnlyList<object> [] Custom JsonConverter instances added to the serializer
Hooks JsonSerializationHooks new() Hooks for intercepting the serialization pipeline

ScanAssemblies

public void ScanAssemblies(params Assembly[] assemblies)

Scans the specified assemblies for all concrete, non-generic subclasses of JsonTypeConfigurationBase (which includes JsonTypeConfiguration<T> and JsonOpenGenericTypeConfiguration<T>) and registers their rules automatically.

Usage:

options.Json.ScanAssemblies(typeof(UserConfiguration).Assembly);

ConfigureAdapter

Use ConfigureAdapter<TAdapter, TOptions> to swap the active serializer adapter or to reach low-level settings of the current adapter that are not exposed through the standard options.Json.* API:

public void ConfigureAdapter<TAdapter, TOptions>(Action<TOptions>? configure = null)
    where TAdapter : IJsonSerializerAdapter

Configures a custom serializer adapter. The built-in default is SystemTextJsonAdapter.

Usage:

// Reach native System.Text.Json settings not covered by the standard API
options.Json.ConfigureAdapter<SystemTextJsonAdapter, JsonSerializerOptions>(serializerOptions =>
{
    serializerOptions.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
    serializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
});

GetSerializerOptions

public object GetSerializerOptions()

Returns the underlying serializer options object from the configured adapter. Useful for directly inspecting the final serializer options at startup.


IJsonTypesConfigurationBuilder

Namespace: AspNetConventions.Serialization.Configuration
Accessed via: options.Json.ConfigureTypes = cfg => { ... }

Provides the fluent API for registering rules across multiple types.

Method Returns Description
Type<T>(Action<IJsonTypeRuleBuilder<T>>) IJsonTypesConfigurationBuilder Registers per-property rules for a specific closed type
OpenGenericType<T>(Action<IJsonTypeRuleBuilder<T>>) IJsonTypesConfigurationBuilder Registers per-property rules for an open generic type; T must itself be a generic type
IgnoreType<T>(IgnoreCondition) IJsonTypesConfigurationBuilder Suppresses every property whose value type is T (or a subtype). Defaults to Always. Highest priority rule
IgnorePropertyName(string, IgnoreCondition) IJsonTypesConfigurationBuilder Suppresses any property matching the given name across all types. Case-insensitive. Defaults to Always

All methods return IJsonTypesConfigurationBuilder for chaining:

options.Json.ConfigureTypes = cfg =>
{
    cfg
        .Type<User>(t => t.Property(x => x.Password).Ignore())
        .Type<Order>(t => t.Property(x => x.InternalRef).Ignore())
        .IgnorePropertyName("StatusCode")
        .IgnoreType<AuditTrail>();
};

IJsonTypeRuleBuilder<T>

Namespace: AspNetConventions.Serialization.Configuration

Provides property selection for a specific type T.

Method Returns Description
Property<TProp>(Expression<Func<T, TProp>>) IJsonPropertyRuleBuilder Selects a property of T using a strongly-typed lambda expression
cfg.Type<User>(type =>
{
    type.Property(x => x.Id);          // selects User.Id
    type.Property(x => x.UserName);    // selects User.UserName
});

IJsonPropertyRuleBuilder

Namespace: AspNetConventions.Serialization.Configuration

Configures the selected property. All methods return IJsonPropertyRuleBuilder for chaining.

Method Returns Description
Ignore(IgnoreCondition) IJsonPropertyRuleBuilder Sets the ignore condition. Defaults to IgnoreCondition.Always
Name(string) IJsonPropertyRuleBuilder Overrides the serialized JSON property name. Takes precedence over CaseStyle
Order(int) IJsonPropertyRuleBuilder Sets the serialization order. Lower values are written first

Chaining example:

type.Property(x => x.OrderId).Name("id").Order(0);

JsonTypeConfiguration<T>

Namespace: AspNetConventions.Serialization.Configuration

Abstract base class for class-based JSON configuration for a single closed type.

public abstract class JsonTypeConfiguration<T> : JsonTypeConfigurationBase
{
    public abstract void Configure(IJsonTypeRuleBuilder<T> rule);
}

Usage:

public class ProductConfiguration : JsonTypeConfiguration<Product>
{
    public override void Configure(IJsonTypeRuleBuilder<Product> rule)
    {
        rule.Property(x => x.CostPrice).Ignore();
        rule.Property(x => x.DisplayName).Name("name");
    }
}

Register via ScanAssemblies or inline:

// Via assembly scanning (recommended)
options.Json.ScanAssemblies(typeof(ProductConfiguration).Assembly);

// Inline — inside the ConfigureTypes delegate
options.Json.ConfigureTypes = cfg =>
{
    cfg.Type<Product>(type => new ProductConfiguration().Configure(type));
};

JsonOpenGenericTypeConfiguration<T>

Namespace: AspNetConventions.Serialization.Configuration

Abstract base class for class-based JSON configuration for open generic types. T must be a closed instantiation of the generic type used as a property-selection template.

public abstract class JsonOpenGenericTypeConfiguration<T> : JsonTypeConfigurationBase
{
    public abstract void Configure(IJsonTypeRuleBuilder<T> rule);
}

Usage:

// Rules are applied to MyApiResponse<string>, MyApiResponse<User>, MyApiResponse<anything>, etc.
public class MyApiResponseConfiguration : JsonOpenGenericTypeConfiguration<MyApiResponse<object>>
{
    public override void Configure(IJsonTypeRuleBuilder<MyApiResponse<object>> rule)
    {
        rule.Property(x => x.Data).Order(3);
        rule.Property(x => x.DebugInfo).Ignore();
    }
}

CasingStyle

Namespace: AspNetConventions.Core.Enums
Accessed via: options.Json.CaseStyle

Value Index JSON property example
CamelCase (default) 2 "userId"
SnakeCase 1 "user_id"
KebabCase 0 "user-id"
PascalCase 3 "UserId"

NumberHandling

Namespace: AspNetConventions.Core.Enums.Json
Accessed via: options.Json.NumberHandling

Value Description
Strict (default) Numbers must be JSON number tokens. Strings are not accepted
AllowReadingFromString Numbers can be read from quoted JSON strings (e.g. "42")
WriteAsString Numbers are written as quoted JSON strings
AllowNamedFloatingPointLiterals Allows NaN, Infinity, and -Infinity as named floating-point values

IgnoreCondition

Namespace: AspNetConventions.Core.Enums.Json
Accessed via: options.Json.IgnoreCondition

This is the global default ignore condition that applies to all properties unless overridden by a more specific rule.

Value Description
Never (default) All properties are always serialized
WhenWritingNull Properties with null values are omitted from output
WhenWritingDefault Properties with default values (null, 0, false, etc.) are omitted
Always All properties are always ignored (not useful as a global default)

JsonSerializationHooks

Namespace: AspNetConventions.Core.Hooks
Accessed via: options.Json.Hooks

Property Delegate signature When called Description
ShouldSerializeType (Type) → bool Once per type at startup Return false to skip all rule processing for a type
ResolvePropertyName (string clrName, Type) → string? Once per property at startup Return a non-null string to override the serialized JSON name. Return null to keep the default
ShouldSerializeProperty (object instance, object? value, string clrName, Type) → bool Every serialization Return false to suppress a property from the output. Called synchronously by the adapter on every serialization — keep it fast
OnTypeResolved (Type, IReadOnlyList<string> jsonNames) → void Once per type at startup Receives the final list of JSON property names. Use for logging or diagnostics
Startup vs. per-serialization

ShouldSerializeType, ResolvePropertyName, and OnTypeResolved run once per type at initialization, then cached by the adapter.

ShouldSerializeProperty runs on every serialization. It is the only hook that can make per-call decisions (e.g. based on the current value or instance state). Property names cannot be changed per request because they are resolved at startup and cached by the adapter. For per-request name changes, use a custom ICaseConverter backed by a scoped service.

Examples:

// Suppress all properties on internal audit types at startup
options.Json.Hooks.ShouldSerializeType = type =>
    !type.Namespace?.StartsWith("MyApp.Internal") ?? true;

// Rename any property called "Id" to "identifier" across all types
options.Json.Hooks.ResolvePropertyName = (clrName, type) =>
    clrName == "Id" ? "identifier" : null;

// Suppress any property whose value is an empty string
options.Json.Hooks.ShouldSerializeProperty = (instance, value, clrName, type) =>
    value is not string s || s.Length > 0;

// Log all resolved types and their JSON property names at startup
options.Json.Hooks.OnTypeResolved = (type, jsonNames) =>
    Console.WriteLine($"[JSON] {type.Name}: {string.Join(", ", jsonNames)}");

Default Values Reference

Option Default
Json.IsEnabled true
Json.CaseStyle CamelCase
Json.CaseConverter null
Json.ConfigureTypes null
Json.WriteIndented false
Json.CaseInsensitive false
Json.AllowTrailingCommas false
Json.MaxDepth 0 (serializer default: 64)
Json.UseStringEnumConverter true
Json.NumberHandling Strict
Json.IgnoreCondition Never
Json.Converters []