Skip to content

[API Proposal]: Polymorphic Deserialization Fallback/Unbound Metadata Capture #116890

Closed
@RyanThomas73

Description

@RyanThomas73

Background and motivation

When using System.Text.Json to deserialize to a polymorphic type decorated with the [JsonPolymorphic] attribute, there is the option set IgnoreUnrecognizedTypeDiscriminators = true and allow deserialization to fallback to instantiating the base type. This useful feature could potentially be improved by allowing additional JSON metadata properties such as the $type discriminator value to be captured on the base type in the fallback case.

The [JsonExtensionData] property can be leveraged to accumulate the unbound JSON properties into a dictionary - and in the fallback scenario described above this would include all properties not explicitly defined on the base type. However the metadata properties, the $type discriminator in particular, is not captured and is effectively lost in such scenarios.

A common scenario where I've wished for such a feature is deserializing batches of events from a stream or json object arrays where the events can contain many different subtypes and the producer(s) add new types semi-frequently. I often want to be able to capture and log a sample of new/unrecognized types for further investigation. Adding a clean out-of-the-box way to do this with the deserialized C# object would go a very long ways in simplifying such processes.

API Proposal

Provide a mechanism, such as a [JsonMetadata] or a [JsonUnrecognizedTypeMetadata] attribute, that can be used indicate to the deserializer when & where such metadata value(s) should be captured.

API Usage

[JsonPolymorphic(IgnoreUnrecognizedTypeDiscriminators = true)]
[JsonDerivedType(typeof(Doggo), "DoggoV1"]
[JsonDerivedType(typeof(Kitteh), "KittehV1"]
public class Animal
{
    [JsonExtensionData]
    [JsonMetadata]
    public Dictionary<string, JsonElement>? ExtensionData { get; set; }
}

Alternative Designs

No response

Risks

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions