Skip to content

Developers should have access to System.Text.Json's default internal converters #63791

Open

Description

Background and Motivation

Currently, the default json converters used for objects and collection types are internal to System.Text.Json. The library uses hardcoded conventions to decide what default converters to apply to each type: for instance classes that implement IEnumerable<T> are automatically treated as collections, and classes that implement IAsyncEnumerable<T> can only be handled by the async-only IAsyncEnumerable converter. As of today, System.Text.Json offers no mechanism for users to override this convention, and we have received a number of questions from the community about this issue:

Currently the best available workaround is for users to either reimplement the default converters, or wrap/cast the values into a type that produces the desired serialization contract. At the same time, we offer no mechanism for users to tweak the serialization behaviour of the default converters other than using attribute annotations (to be ameliorated once #63686 has been implemented). Related issues:

Proposal

This story proposes making the default internal converters public, so that users are free to opt in to specific converter strategies for their types. Consider the following example:

public class MyClass : IEnumerable<int>, IAsyncEnumerable<int>
{
}

By default, members of type MyClass are serialized as IAsyncEnumerables. Users can still force IEnumerable semantics if they cast the instance to IEnumerable<int>, however there is currently no way to serialize the type as an object. By exposing the default converter types, we can decorate our type definition with attributes:

[JsonConverter(typeof(JsonObjectConverter))] // serialize as object
// [JsonConverter(typeof(JsonCollectionConverter))] // serialize as collection
// [JsonConverter(typeof(JsonAsyncEnumerableConverter)] // serialize as IAsyncEnumerable
public class MyClass : IEnumerable<int>, IAsyncEnumerable<int>
{
}

Moreover, we should consider exposing parameterization on the converters so that users can configure the contract (for example what #38514 is asking for).

NB we should update the source generator so that relevant JsonPropertyAttribute annotations are recognized and trigger relevant metadata generation, cf. #82001 (comment)

Progress

  • Prototyping work
  • API proposal
  • Implementation & tests
  • Documentation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions