-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
System.Text.Json fast path serialization not working with combined contexts #71933
Comments
Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis Issue DetailsThe internal logic governing use of fast path serialization is dependent on Lines 72 to 80 in 7d2be1e
or Lines 130 to 134 in 7d2be1e
The introduction of contract customization has made it possible for source generated metadata to be associated with options instances not attached to a [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(HighLowTemps))]
public partial class SerializationContext : JsonSerializerContext {}
public class HighLowTemps
{
public int High { get; set; }
public int Low { get; set; }
}
[Fact]
public static void CombiningContexts_FastPathSerialization()
{
var value = new HighLowTemps { High = 40, Low = 30 };
string expectedJson = """{"High":40,"Low":30}""";
// Sanity check -- default context
var options = new JsonSerializerOptions { TypeInfoResolver = SerializationContext.Default };
string json = JsonSerializer.Serialize(value, options);
Assert.Equal(expectedJson, json);
// Using a trivial combined context
options = new JsonSerializerOptions { TypeInfoResolver = JsonTypeInfoResolver.Combine(SerializationContext.Default) };
json = JsonSerializer.Serialize(value, options); // 'JsonSerializerContext' '<null>' did not provide property metadata
// for type 'System.Text.Json.SourceGeneration.Tests.HighLowTemps'.
Assert.Equal(expectedJson, json);
} In order to get the issue fixed, it is necessary for source gen namespace System.Text.Json.Serialization.Metadata;
public partial class JsonObjectInfoValues<T>
{
public JsonSerializerContext? JsonSerializerContext { get; init; }
}
public partial class JsonCollectionInfoValues<T>
{
public JsonSerializerContext? JsonSerializerContext { get; init; }
}
public partial class JsonCollectionInfoValues<T>
{
public JsonSerializerContext? JsonSerializerContext { get; init; }
}
public partial static class JsonMetadataServices
{
public static JsonTypeInfo<T> CreateValueInfo<T>(JsonSerializerOptions options, JsonConverter converter); // existing overload
public static JsonTypeInfo<T> CreateValueInfo<T>(JsonSerializerOptions options, JsonConverter converter, JsonSerializerContext? context);
}
|
I'm aware of the issue although I'd take slightly different approach to the fix. Rather than trying to preserve this logic I'd focus on what IMO following approach should be taken:
also I'm not sure if we can ever claim SerializeHandler will work correctly when customization happens - i.e. say we generated a SerializeHandler for struct with int and then we customize We should figure out if this even makes sense fixing considering number of edge case scenarios fixing this could introduce. The only moment where we can currently safely use fast path is what we're currently doing (when context is assigned directly as TypeInfoResolver) |
Looks good as proposed. Based on discussion it seems like EditorBrowsable(Never) is justified, since it's mostly distracting to callers outside of the serializer/sourcegen dichotomy. namespace System.Text.Json.Serialization.Metadata;
public class JsonTypeInfo
{
[EditorBrowsable(EditorBrowsableState.Never)]
public IJsonTypeInfoResolver? OriginatingResolver { get; set; } = null;
} |
EDIT: See API proposal at the bottom of this post.
The internal logic governing use of fast path serialization is dependent on
JsonSerializerOptions
encapsulating aJsonSerializerContext
instance. Consider:runtime/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonMetadataServicesConverter.cs
Lines 72 to 80 in 7d2be1e
or
runtime/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/SourceGenJsonTypeInfoOfT.cs
Lines 130 to 134 in 7d2be1e
or
runtime/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs
Lines 452 to 455 in 26da83d
The introduction of contract customization has made it possible for source generated metadata to be associated with options instances not attached to a
JsonSerializerContext
. This can result in inconsistency, consider:In order to get the issue fixed, it is necessary for source gen
JsonTypeInfo<T>
to encapsulate a reference to their originatingJsonSerializerContext
.API Proposal
The text was updated successfully, but these errors were encountered: