dotnet / dotnet/aspnetcore

[API Proposal]: STJ `SystemTextJsonOutputFormatter` output type selector

Open
#55,629 2 comments 0 reactions 0 assignees View on GitHub
api-suggestion area-mvc untriaged
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 6h
Merged PRs (30d)
290

Description

### Background and motivation

Right now the default `SystemTextJsonOutputFormatter` internally decides what type to serialize (in `WriteResponseBodyAsync`). In my case I'd like to keep the controlers response type (an Interface) that now gets broken down to it's actual class.

Right now the type to serialize gets chosen here: https://github.com/dotnet/aspnetcore/blob/333629e6c3d4ee301bb5985f0de66f447f6226ba/src/Mvc/Mvc.Core/src/Formatters/SystemTextJsonOutputFormatter.cs#L74

and checked here: https://github.com/dotnet/aspnetcore/blob/333629e6c3d4ee301bb5985f0de66f447f6226ba/src/Mvc/Mvc.Core/src/Formatters/SystemTextJsonOutputFormatter.cs#L91

It'd be great to have an overrideable method where the `jsonTypeInfo` is selected.

### API Proposal

```
protected JsonTypeInfo? GetTypeInfo(OutputFormatterWriteContext context)
{
// context.ObjectType reflects the declared model type when specified.
// For polymorphic scenarios where the user declares a return type, but returns a derived type,
// we want to serialize all the properties on the derived type. This keeps parity with
// the behavior you get when the user does not declare the return type.
// To enable this our best option is to check if the JsonTypeInfo for the declared type is valid,
// if it is use it. If it isn't, serialize the value as 'object' and let JsonSerializer serialize it as necessary.
JsonTypeInfo? jsonTypeInfo = null;
if (context.ObjectType is not null)
{
var declaredTypeJsonInfo = SerializerOptions.GetTypeInfo(context.ObjectType);

var runtimeType = context.Object?.GetType();
if (declaredTypeJsonInfo.ShouldUseWith(runtimeType))
{
jsonTypeInfo = declaredTypeJsonInfo;
}
}
return jsonTypeInfo;
}
```

### API Usage

```
protected override JsonTypeInfo? GetTypeInfo(OutputFormatterWriteContext context)
{
if (context.ObjectType?.IsInterface == true) { return SerializerOptions.GetTypeInfo(context.ObjectType); }
return base.GetTypeInfo(context);
}
```

### Alternative Designs

_No response_

### Risks

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.