Skip to content

Add an AppContext switch that disables using reflection by default in JsonSerializerOptions #83279

@eiriktsarpalis

Description

@eiriktsarpalis

Background and motivation

Since the release of the JsonSerializerOptions type in .NET Core 3, the default behavior of unconfigured options instances created with the default constructor has been to use reflection-based contract resolution. With the advent of new features such as the source generator and contract customization that go beyond reflection, this default behavior has forced a number of interesting design decisions on the type itself and other STJ components: for example, it has made the semantics of configuring the TypeInfoResolver property particularly difficult to work with.

We've received a lot of feedback about the issue from the aspnetcore team, who have been trying to make minimal APIs work in NativeAOT in a way that is consistent with CoreCLR. They ultimately addressed the issue on the aspnet layer using a special EnsureJsonTrimmability feature flag that was shipped in Preview 1. When turned on, this flag disables reflection-by-default and ensures that only user-provided configuration is being used. When left turned off, it offers the predictable and backward-compatible experience that works well in CoreCLR apps. What's more, the feature flag is recognized by the linker, ensuring that reflection components don't get rooted when turned on.

There's consensus between the JSON crew and the aspnet team that this flag should be moved to the System.Text.Json layer. This issue proposes the creation of a System.Text.Json.JsonSerializer.UseReflectionDefault feature flag that offers similar semantics to the current aspnetcore implementation.

API Proposal

As mentioned above, we want to introduce a System.Text.Json.JsonSerializer.IsReflectionEnabledByDefault feature flag. Note that this diverges from the namespace/naming convention used in the System.Text.Json.Serialization.EnableSourceGenReflectionFallback compatibility switch that was introduced in .NET 7.

Moreover, we would require the following changes to API:

namespace System.Text.Json;

public partial static class JsonSerializer
{
    // maps to the feature switch, and is registered in ILLink.Substitutions.xml
    public static bool IsReflectionEnabledByDefault { get; } // true if no feature switch is set.
}

Related to #74492.

API Usage

if (JsonSerializer.IsReflectionEnabledByDefault)
{
     // branch trimmed by the linker if the 
     // feature switch is set to false at link time.
     JsonSerializer.Serialize(value);
}

cc @eerhardt @davidfowl @halter73

Metadata

Metadata

Labels

api-approvedAPI was approved in API review, it can be implementedarea-System.Text.JsonblockingMarks issues that we want to fast track in order to unblock other important workpartner-impactThis issue impacts a partner who needs to be kept updated

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions