Does polymorphic serde work in System.Text.Json with source generation? #115218
-
Hi, I'm trying to turn on native AOT for my app which relies on polymorphic serialization/deserialization with System.Text.Json. Before native AOT, we have a custom polimorphic type info resolver exactly like it mentioned in this doc: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/polymorphism#configure-polymorphism-with-the-contract-model. Then
With native AOT enabled, the
Now, with Does anyone know if the TypeInfoResolver configured for polymorphic deserialization works with source generation in System.Test.Json? or am I missing something? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
Found some discussions in this issue and tested it seems to work: #85884 (comment), as in, it does successfully serialize and deserialize in VS debugging mode with AOT enabled, however, when I attempted to publish the app I get the following errors: So it looks like for polymorphic serde to work, we need to use the overloads with |
Beta Was this translation helpful? Give feedback.
-
I have never tried/seen "sneaking" a reflection-based resolver (DefaultJsonTypeInfoResolver is reflection-based) into the source-generated resolver (your JsonSerializerContext-derived class is the source-gen-based resolver). I wouldn't be surprised if the source-gen resolver simply ignores the TypeInfoResolver set in the options provided for its constructor and uses the JsonTypeInfos it itself produces, but i don't know. However, i would suggest a different approach. I am not 100% sure if what i describe below is sufficient for making it work for AoT, or whether there are further pitfalls i didn't consider. But anyways, on with the show... Instead of attempting to fall back onto a reflection-based resolver, modify the JsonTypeInfo's that are created by the JsonSerializerContext. This is done with the help of the You would basically transplant the logic of your PolymorphicTypeResolver.GetTypeInfo method into the modifier delegate provided to [JsonSerializable(typeof(IMessage))]
[JsonSerializable(typeof(MessageA))]
[JsonSerializable(typeof(MessageB))]
public partial class SourceGenerationContext : JsonSerializerContext
{
public static readonly IJsonTypeInfoResolver Custom = new SourceGenerationContext(
new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.IgnoreCycles }
).WithAddedModifier(ModifyTypeInfos);
static void ModifyTypeInfos(System.Text.Json.Serialization.Metadata.JsonTypeInfo typeInfo)
{
... the logic from your original PolymorphicTypeResolver.GetTypeInfo method ...
}
} You would then acquire the desired JsonTypeInfo from this modified resolver and pass it to the (de)serialization method, e.g.: JsonSerializer.Deserialize(
json,
SourceGenerationContext.Custom.GetTypeInfo(typeof(IMessage), JsonSerializationOptions.Default)
); (Again, as said in the beginning, i am unsure if this will solve the problem 100%, but i guess it's worth a try...) |
Beta Was this translation helpful? Give feedback.
I have never tried/seen "sneaking" a reflection-based resolver (DefaultJsonTypeInfoResolver is reflection-based) into the source-generated resolver (your JsonSerializerContext-derived class is the source-gen-based resolver). I wouldn't be surprised if the source-gen resolver simply ignores the TypeInfoResolver set in the options provided for its constructor and uses the JsonTypeInfos it itself produces, but i don't know.
However, i would suggest a different approach. I am not 100% sure if what i describe below is sufficient for making it work for AoT, or whether there are further pitfalls i didn't consider. But anyways, on with the show...
Instead of attempting to fall back onto a reflect…