Background & Motivation
The System.Text.Json reflection-based serializer makes it possible for users to supply JsonSerializerOptions instances that don't have a TypeInfoResolver property explicitly configured. It does this by silently populating the TypeInfoResolver property with a reflection-based DefaultJsonTypeInfoResolver value and then locking the instance for further modification.
Using publicly available APIs, this semantic can be emulated as follows:
void ConfigureForReflection(JsonSerializerOptions options)
{
options.TypeInfoResolver ??= new DefaultJsonTypeInfoResolver();
options.MakeReadOnly();
}
The problem with this approach is that it isn't thread safe when applied to the same options instance. I encountered this issue when attempting to implement reflection-based initialization in System.Net.Http.Json (cf. #89830), which can only access public STJ APIs. At the moment, the only viable workaround for libraries like System.Net.Http.Json is to do the following:
if (options.TypeInfoResolver is null)
{
// Run a basic serialization operation to force thread-safe initialization of the options instance.
JsonSerializer.Deserialize<int>("0"u8, options);
}
While the above works, it is kind of wasteful in that it forces an unnecessary serialization operation. We need access to the API that simply primes the options instance for reflection-based usage.
API Proposal
Add a method to JsonSerializerOptions for configuring using reflection-based defaults:
namespace System.Text.Json;
public partial class JsonSerializerOptions
{
// Throws IOE if TypeInfoResolver is null
public void MakeReadOnly();
+ // Populates TypeInfoResolver with DefaultJsonTypeInfoResolver if null
+ // (or the empty resolver if the IsReflectionEnabledDefault switch is disabled)
+ [RequiresUnreferencedCode, RequiresDynamicCode]
+ public void MakeReadOnlyWithReflectionDefaults();
}
cc @eerhardt