Skip to content

Reduce generic usage of JsonConverter<T> for object and collection converters #36784

@steveharter

Description

@steveharter

Currently, the JsonConverter<T> base class is closed with T being the Type declared by a property or the root type passed to the serializer. This helps avoid boxing for value converters, such as for an int property and is an important feature for performance. However, the same pattern is used for object- and collection-converters which typically use reference types, not value types.

By changing this to use System.Object for T instead of the actual Type reduces assembly size and reduces memory consumption by avoiding JITing (todo: quantify) and calls to Type.MakeGenericType(). In addition, limiting usage of generics helps with AOT scenarios and may be required in certain cases (pending testing of Xamarin on iOS and Android devices). See the 5.0 serializer goals for more detail

For example,

  • For an int Type, T is System.Int32 (value converter).
  • For a MyPOCO Type, T is MyPOCO (object converter).
  • For a List<int> Type, T is List<int> (collection converter).

Proposal:

  • For object and collection converters, T will be System.Object instead of the actual Type. Note there are alternatives that need to be considered such as not even using generics for these types of converters, although that makes it more difficult for the serializer design to compose multiple converters (e.g. List<Dictionary<string, MyPoco>> which uses 4 converters).
  • The base class of JsonConverter<T> which is JsonConverter could add Read- and Write- method that directly operate on System.Object instead of T. This enables loosely-typed scenario which are not easy or performant today (re-entry into the serializer or usage of Type.MakeGenericType is necessary).

Currently in 5.0, a converter is returned by the public JsonSerializerOptions.GetConverter(Type type) method. In 3.0\3.1 this method returned null for objects and collections since the implementation for those did not share the same infrastructure as value converters. In 5.0 the GetConverter method returns a non-null converter such as JsonConverter<List<int>>. It is important for 5.0 that we don't expose implementation details that we may later want to change. We may want to change the semantics in 5.0 to instead to return null for object and collection converters, or to return JsonConverter<object>.

Metadata

Metadata

Assignees

Labels

api-needs-workAPI needs work before it is approved, it is NOT ready for implementationarea-System.Text.Json

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions