-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Description
Background and motivation
The STJ source generator's implementation of the JsonSerializerContext.GetTypeInfo and IJsonTypeInfoResolver.GetTypeInfo methods are currently duplicated:
public override global::System.Text.Json.Serialization.Metadata.JsonTypeInfo? GetTypeInfo(global::System.Type type)
{
if (type == typeof(global::TestModel))
{
return this.TestModel;
}
if (type == typeof(global::System.Int32))
{
return this.Int32;
}
return null;
}
global::System.Text.Json.Serialization.Metadata.JsonTypeInfo? global::System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver.GetTypeInfo(global::System.Type type, global::System.Text.Json.JsonSerializerOptions options)
{
if (type == typeof(global::TestModel))
{
return Create_TestModel(options, makeReadOnly: false);
}
if (type == typeof(global::System.Int32))
{
return Create_Int32(options, makeReadOnly: false);
}
return null;
}The size of these methods increases with the number of generated types, so in the interest of size reduction we would at least want to eliminate the duplication. The first GetTypeInfo method could be implemented by replacing it with
public override global::System.Text.Json.Serialization.Metadata.JsonTypeInfo? GetTypeInfo(global::System.Type type)
=> Options.GetTypeInfo(type);There is a however a snag, since JsonSerializerContext.GetTypeInfo needs to return null for unsupported types, whereas JsonSerializerOptions.GetTypeInfo is non-nullable and returns NotSupportedException for unsupported types.
API Proposal
namespace System.Text.Json;
public partial class JsonSerializerOptions
{
public JsonTypeInfo GetTypeInfo(Type type);
+ public bool TryGetTypeInfo(Type type, [NotNullWhen(true)] out JsonTypeInfo? typeInfo);
}API Usage
The source generator could then implement the first GetTypeInfo as follows:
public override global::System.Text.Json.Serialization.Metadata.JsonTypeInfo? GetTypeInfo(global::System.Type type)
{
Options.TryGetTypeInfo(type, out JsonTypeInfo? result);
return result;
}Testing against our own source gen test projects, the change contributes to ~2.2% size reduction to generated source files and just over 1.2% to the test assemblies (which includes test code beyond just the source generated contexts). A minor yet measurable improvement.
Alternative Designs
-
Do not ship the a new API and instead source generate
public override global::System.Text.Json.Serialization.Metadata.JsonTypeInfo? GetTypeInfo(global::System.Type type) { try { return Options.GetTypeInfo(type); } catch (NotSupportedException) { return null; } }
-
Make the existing
GetTypeInfomethod nullable:public partial class JsonSerializerOptions { - public JsonTypeInfo GetTypeInfo(Type type); + public JsonTypeInfo? GetTypeInfo(Type type); }It would return
nullwhere the method currently throws, so technically this is not a breaking change but it would trigger nullability warnings in places where it previous didn't apply.
Risks
No response